在 C# 中为 SQLite 形成数据结构时遇到问题
Trouble forming data structure for SQLite in C#
我正在尝试构建一个非常简单的 Xamarin 应用程序,其功能类似于 Exercise/Day Planner。 SQLite 数据库应该保存 "Day"s table,并且每一天都应该与 "Activity"s table 相关,它可以查询那几天 "Activity"s。这些 "Activity" 应该属于某种类型,为简单起见,我们可以说是 "Walk"、"Run" 或 "Swim"。然后,用户应该能够对该数据库执行基本的 CRUD 操作,以回忆以前的日子及其相关活动。理想情况下,使用 SQLiteNetExtensions 库,我应该能够进行简单的调用来检索数据:
SQLiteAsyncConnection connection = DependencyService.Get<ISQLiteDb>().GetConnection();
var day = await connection.GetWithChildrenAsync<Day>(primaryKey, recursive = true);
模型(简化):
using SQLite;
using SQLiteNetExtensions.Attributes;
using System;
using System.Collections.Generic;
public class Day {
public Day()
{
Date = DateTime.Now;
}
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public DateTime Date { get; set; }
[OneToMany]
public List<Activity> Activities { get; set; }
}
public abstract class Activity
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[ManyToOne(typeof(Day))]
public Day Day { get; set; }
[ForeignKey]
public int DayRefId { get; set; }
public double Input { get; set; }
public virtual double OutputKms { get; set; }
}
public class Walk : Activity
{
public override double OutputKms { get { return Input * 3; } }
}
public class Run: Activity
{
public override double OutputKms { get { return Input * 5; } }
}
public class Swim: Activity
{
public override double OutputKms { get { return Input * 3; } }
}
我正在使用以下代码初始化我的数据库:
using SQLite;
using Xamarin.Forms;
using SQLiteNetExtensionsAsync.Extensions;
public async static Task InitDb()
{
SQLiteAsyncConnection connection = DependencyService.Get<ISQLiteDb>().GetConnection();
await connection.CreateTableAsync<Day>();
await connection.CreateTableAsync<Activity>();
await connection.CreateTableAsync<Walk>();
await connection.CreateTableAsync<Run>();
await connection.CreateTableAsync<Swim>();
}
问题是 SQLite 不喜欢 table 基于抽象 类。在我尝试创建 "Activity" table 的行中,出现以下编译错误:
Error CS0310 'Activity' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T'
我知道 Entity Framework 支持使用抽象 类,但如果可能,我宁愿坚持使用 SQLite。
这似乎是一个简单的问题,但如果不求助于最简单的 poco 对象并编写大量重复代码,我就很难解决。
我的问题是如何更好地重构我的代码,我可以使用哪些库或者我可以编写什么样的映射来实现它。感谢任何反馈。谢谢!
Sqlite.net 和 Sqlite.net 扩展中的所有类型都是 T : new()
,因此您将无法使用抽象 classes。代码如下:
[OneToMany]
public List<Activity> Activities { get; set; }
其中 Activity
是一个抽象 class 是行不通的,因为很难弄清楚 table 数据应该来自哪里。
它可以为Activity
、Walk
、Swim
、Run
构造tables(如果你让Activity
不抽象),但 Sqlite.net 扩展程序将无法创建关系,因此不会撤回数据。
就我个人而言,我不会在你坚持的模型中有这个 属性 的逻辑,(你可能这样做是为了简化问题并且有更多的逻辑):
public override double OutputKms { get { return Input * 3; } }
您可以将 Walk
、Run
、Swim
中的 3、5、3 的任何乘数重构为 属性 或存储一个 activity 在 activity class 中键入枚举,而不是像这样抽象:
public class Activity
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[ManyToOne(typeof(Day))]
public Day Day { get; set; }
[ForeignKey]
public int DayRefId { get; set; }
public double Input { get; set; }
public ActivityType ActivityType { get; set; }
}
public enum ActivityType
{
Walk,
Run,
Swim
}
另一种选择是为数据库创建不同的模型,这些模型是映射到更复杂的应用程序模型的 Pocos。可能使用 AutoMapper
我正在尝试构建一个非常简单的 Xamarin 应用程序,其功能类似于 Exercise/Day Planner。 SQLite 数据库应该保存 "Day"s table,并且每一天都应该与 "Activity"s table 相关,它可以查询那几天 "Activity"s。这些 "Activity" 应该属于某种类型,为简单起见,我们可以说是 "Walk"、"Run" 或 "Swim"。然后,用户应该能够对该数据库执行基本的 CRUD 操作,以回忆以前的日子及其相关活动。理想情况下,使用 SQLiteNetExtensions 库,我应该能够进行简单的调用来检索数据:
SQLiteAsyncConnection connection = DependencyService.Get<ISQLiteDb>().GetConnection();
var day = await connection.GetWithChildrenAsync<Day>(primaryKey, recursive = true);
模型(简化):
using SQLite;
using SQLiteNetExtensions.Attributes;
using System;
using System.Collections.Generic;
public class Day {
public Day()
{
Date = DateTime.Now;
}
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public DateTime Date { get; set; }
[OneToMany]
public List<Activity> Activities { get; set; }
}
public abstract class Activity
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[ManyToOne(typeof(Day))]
public Day Day { get; set; }
[ForeignKey]
public int DayRefId { get; set; }
public double Input { get; set; }
public virtual double OutputKms { get; set; }
}
public class Walk : Activity
{
public override double OutputKms { get { return Input * 3; } }
}
public class Run: Activity
{
public override double OutputKms { get { return Input * 5; } }
}
public class Swim: Activity
{
public override double OutputKms { get { return Input * 3; } }
}
我正在使用以下代码初始化我的数据库:
using SQLite;
using Xamarin.Forms;
using SQLiteNetExtensionsAsync.Extensions;
public async static Task InitDb()
{
SQLiteAsyncConnection connection = DependencyService.Get<ISQLiteDb>().GetConnection();
await connection.CreateTableAsync<Day>();
await connection.CreateTableAsync<Activity>();
await connection.CreateTableAsync<Walk>();
await connection.CreateTableAsync<Run>();
await connection.CreateTableAsync<Swim>();
}
问题是 SQLite 不喜欢 table 基于抽象 类。在我尝试创建 "Activity" table 的行中,出现以下编译错误:
Error CS0310 'Activity' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T'
我知道 Entity Framework 支持使用抽象 类,但如果可能,我宁愿坚持使用 SQLite。
这似乎是一个简单的问题,但如果不求助于最简单的 poco 对象并编写大量重复代码,我就很难解决。
我的问题是如何更好地重构我的代码,我可以使用哪些库或者我可以编写什么样的映射来实现它。感谢任何反馈。谢谢!
Sqlite.net 和 Sqlite.net 扩展中的所有类型都是 T : new()
,因此您将无法使用抽象 classes。代码如下:
[OneToMany]
public List<Activity> Activities { get; set; }
其中 Activity
是一个抽象 class 是行不通的,因为很难弄清楚 table 数据应该来自哪里。
它可以为Activity
、Walk
、Swim
、Run
构造tables(如果你让Activity
不抽象),但 Sqlite.net 扩展程序将无法创建关系,因此不会撤回数据。
就我个人而言,我不会在你坚持的模型中有这个 属性 的逻辑,(你可能这样做是为了简化问题并且有更多的逻辑):
public override double OutputKms { get { return Input * 3; } }
您可以将 Walk
、Run
、Swim
中的 3、5、3 的任何乘数重构为 属性 或存储一个 activity 在 activity class 中键入枚举,而不是像这样抽象:
public class Activity
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[ManyToOne(typeof(Day))]
public Day Day { get; set; }
[ForeignKey]
public int DayRefId { get; set; }
public double Input { get; set; }
public ActivityType ActivityType { get; set; }
}
public enum ActivityType
{
Walk,
Run,
Swim
}
另一种选择是为数据库创建不同的模型,这些模型是映射到更复杂的应用程序模型的 Pocos。可能使用 AutoMapper