SubSonic不能识别SQLite外键

3
我正在使用SubSonic 3.0.0.3,但似乎无法让ActiveRecord.tt文件识别和生成代码以处理我SQLite数据库中的外键和关联。我认为它可以很好地生成其他所有内容,但是在查看其他在线片段后,我发现除了每个表的单个类之外,应该有更多生成的代码。在查看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如何处理一对多和多对多的关系。以下是SQLite Expert针对我的小型数据库生成的DDL:
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 Expert显示它们已开启,当我在一个地方更改数据时,例如Person的PersonID,确实会在Dog和GroupPersons表中更改该PersonID。我尝试重新将数据库添加到项目中,“运行自定义工具”以再次执行.tt文件,甚至删除它们并重新添加它们。我可以构建一个简单的项目来执行简单的查询和插入,但是我刚刚尝试更改单个Person、Dog或Group的主键并x.Save(),但是System.Data.SQLite为所有三者抛出了异常,说SQLite error near "WHERE":syntax error. 在Save()处。
你有什么建议我接下来应该做些什么?

x.Save() 函数中使用了什么查询? - MPelletier
2个回答

5
似乎在文件“SQLite.ttinclude”中没有为每个表分配FKTables属性。因此,我添加了一些代码行并成功生成了外键代码:
在第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);

这是用于生成外键代码的。

此外,当您需要删除一个在另一个表中作为外键的列的记录时,您可能会遇到问题。例如: Person(Id,Name) Dog(Id,#PersonId) 如果您将#PersonId外键设置为“设置为空”,那么这种方法不起作用,因为默认情况下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上的开端非常棒! - MPelletier

1

我正在思考这个问题。似乎有两个问题:

  • 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]));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接