【问题标题】:SubSonic not recognizing SQLite foreign keysSubSonic 无法识别 SQLite 外键
【发布时间】:2010-08-24 01:14:09
【问题描述】:

我使用的是 SubSonic 3.0.0.3,我似乎无法让 ActiveRecord .tt 文件识别和生成 SQLite 数据库中的外键和关系的代码。

我认为它生成其他所有内容都很好,但是在查看其他在线 sn-ps 之后,看起来应该有更多生成的代码,而不仅仅是 ActiveRecord.csStructs.cs 中的每个表中的单个类。在Structs.cs 内部,IsForeignKey 对于每一列总是false,即使是我定义了外键的那些。此外,每个生成的 ActiveRecord 类中的每个Foreign Keys 区域都是空的。

我在项目中使用 VS2008 并引用了 SubSonic 3.0.0.3、System.Data.SQLite 1.0.66.0 和 System.Data.SQLite.Linq 2.0.38.0。我使用 SQLite Expert Personal 3.1.0.2076 创建了数据库。我制作了一些虚拟表来尝试测试 SubSonic 如何处理 one:many 和 many:many 关系。这是为我的小型数据库吐出的 DDL SQLite Expert:

CREATE TABLE [Person] (
[PersonID] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,
[PersonName] TEXT  NOT NULL,
[PersonAge] INT  NOT NULL
);

CREATE TABLE [Group] (
[GroupID] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,
[GroupName] TEXT  NOT NULL,
[GroupDescription] TEXT  NOT NULL
);

CREATE TABLE [Dog] (
  [DogID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
  [PersonID] INT NOT NULL CONSTRAINT [DogPersonFK] REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE, 
  [DogName] TEXT NOT NULL);

CREATE TABLE [GroupPersons] (
  [GroupID] INTEGER NOT NULL CONSTRAINT [GroupPersonToGroupFK] REFERENCES [Group]([GroupID]) ON DELETE CASCADE ON UPDATE CASCADE, 
  [PersonID] INTEGER NOT NULL CONSTRAINT [GroupPersonToPersonFK] REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE, 
  CONSTRAINT [sqlite_autoindex_GroupPersons_1] PRIMARY KEY ([GroupID], [PersonID]));

我知道外键已启用并在数据库中工作 - SQLite 专家表示它们已启用,当我在一个地方更改数据时,例如 Person 的 PersonID,它确实会更改 Dog 和 GroupPersons 表中的 PersonID。我尝试将数据库重新添加到项目中,“运行自定义工具”以使 .tt 文件再次执行,甚至删除它们并将它们添加回来。我可以构建一个简单的项目来执行简单的查询和插入,但是我刚才尝试更改单个人、狗或组的主键和 x.Save() 但 System.Data.SQLite 抛出了异常所有三个,在 Save() 中说 SQLite error near "WHERE":syntax error.

对我接下来应该尝试做什么有什么建议吗?

【问题讨论】:

  • x.Save() 函数中使用的查询是什么?

标签: c# sqlite subsonic foreign-keys subsonic3


【解决方案1】:

似乎每个表的 FKTables 属性未在文件“SQLite.ttinclude”中分配。所以我添加了一些代码行并设法生成外键代码:

在第 16 行 (var schema = conn.GetSchema("COLUMNS");) 之后,插入:

var schemaForeignKeys = conn.GetSchema("FOREIGNKEYS");

在第 29 行 (tbl.Name = row["TABLE_NAME"].ToString();) 之后,插入:

tbl.FKTables = new List<FKTable>();
var foreignKeyTables = schemaForeignKeys.Select("TABLE_NAME='" + tbl.Name + "'");
foreach (var foreignKeyTable in foreignKeyTables) {
    FKTable foreignKey = new FKTable();
    foreignKey.ThisTable = foreignKeyTable["TABLE_NAME"].ToString();
    foreignKey.ThisColumn = foreignKeyTable["FKEY_FROM_COLUMN"].ToString();
    foreignKey.OtherTable = foreignKeyTable["FKEY_TO_TABLE"].ToString();
    foreignKey.OtherColumn = foreignKeyTable["FKEY_TO_COLUMN"].ToString();
    foreignKey.OtherClass = CleanUp(foreignKey.OtherTable);
    foreignKey.OtherQueryable = foreignKey.OtherClass;
    tbl.FKTables.Add(foreignKey);
}

在第 53 行 (col.IsNullable=row["IS_NULLABLE"].ToString()=="True";) 之后,插入:

col.IsForeignKey = tbl.FKTables.Any(x => x.ThisColumn == col.Name);

这是为了生成外键码。

此外,当您必须删除在另一个表中具有作为外键的列的记录时,您可能会遇到问题?举个例子 : 人(身份证,姓名) 狗(ID,#PersonId) 如果您已将#PersonId 外键删除操作设置为“SET TO NULL”,这将不起作用,因为在 SQLite 3.6.23.1(Data.SQLite 1.0.66.0 使用的版本)中默认禁用外键支持。 要启用外键支持,您必须对每个连接执行此命令:

PRAGMA foreign_keys = ON;

现在,Data.SQLite 不支持此功能,但它会(在 1.0.67.0 版中,http://sqlite-dotnet2.cvs.sourceforge.net/viewvc/sqlite-dotnet2/SQLite.NET/System.Data.SQLite/SQLiteConnection.cs?r1=1.80&r2=1.81)。

所以你必须等待发布,或者你可以(像我一样)下载 Data.SQLite 源代码并编译最后一个版本。它对我很有用。

祝你好运。 对不起我的英语:)

【讨论】:

  • 你在 SO 上有一个很好的开始!
【解决方案2】:

我正在尝试对此进行推理。手头似乎有两个问题:

  • Subsonic 无法识别您的外键
  • x.Save() 函数发送该错误消息。

SQLite 将自行强制执行引用完整性,因此虽然 Subsonic 看不到外部引用,但 SQLite 可以,这就是您的更新通过的原因。 Subsonic 不驱动 SQLite,它自己驱动,这很好。

我正在尝试了解 SubSonic 做什么。同时,我有这个假设:表定义没有正确解析。如果x.Save()使用的是自动生成的SQL,那这两个问题可能真的只是一个问题。

要验证(或无效)这个假设,您可以尝试这样定义表,将外键作为表属性,而不是特定字段的属性:

CREATE TABLE [Dog] (
  [DogID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 
  [PersonID] INTEGER NOT NULL,
  [DogName] TEXT NOT NULL,
  FOREIGN KEY ([PersonID]) REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE);

CREATE TABLE [GroupPersons] (
  [GroupID] INTEGER NOT NULL,
  [PersonID] INTEGER NOT NULL,
  FOREIGN KEY ([GroupID]) REFERENCES [Group]([GroupID]) ON DELETE CASCADE ON UPDATE CASCADE,
  FOREIGN KEY ([PersonID]) REFERENCES [Person]([PersonID]) ON DELETE CASCADE ON UPDATE CASCADE,
  PRIMARY KEY ([GroupID], [PersonID]));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    相关资源
    最近更新 更多