SubSonic无法识别SQLite外键

时间:2010-08-24 01:14:09

标签: c# sqlite subsonic foreign-keys subsonic3

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

我认为它可以很好地生成其他所有内容,但在查看其他在线代码后,看起来应该有更多生成的代码,而不仅仅是ActiveRecord.csStructs.cs中每个表的单个类。查看Structs.cs内部,IsForeignKey对于每列始终为false,即使是我为其定义了外键的列也是Foreign Keys。此外,每个生成的ActiveRecord类中的每个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])); 区域都是空的。

我正在使用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如何处理一个:很多很多:许多关系。这是DDL SQLite Expert吐出我的小型数据库:

SQLite error near "WHERE":syntax error.

我知道外键已启用并在数据库中工作 - SQLite Expert说他们正在使用,当我在一个地方更改数据时,比如Person的PersonID,它确实改变了Dog和GroupPersons表中的PersonID。我已经尝试将数据库重新添加到项目中,“运行自定义工具”以使.tt文件再次执行,甚至删除它们并将其添加回来。我可以得到一个简单的项目来构建执行简单的查询和插入,但是我现在尝试更改单个Person,Dog或Group的主键和x.Save(),但是System.Data.SQLite抛出异常这三个,在Save()上说{{1}}。

对于我接下来应该尝试做什么的任何建议?

2 个答案:

答案 0 :(得分:5)

似乎每个表的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外键on-delete操作设置为“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源并编译最后一个版本。它对我很有用。

祝你好运。 抱歉我的英语:)

答案 1 :(得分:1)

我试图解释这一点。手头似乎有两个问题:

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

SQLite将自己强制执行引用完整性,因此虽然Subsonic没有看到外部引用,但SQLite会这样做,这就是您的更新通过的原因。亚力士没有推动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]));