2010-08-24 128 views
3

我使用的是SubSonic 3.0.0.3,我似乎無法獲得ActiveRecord .tt文件來識別和生成我的SQLite數據庫中的外鍵和關係代碼。SubSonic不識別SQLite外鍵

我認爲它產生的一切都很好,但在看了其他片段後,看起來應該有更多生成的代碼,而不僅僅是我的每個表格的ActiveRecord.csStructs.cs中的單個類。尋找Structs.csIsForeignKey總是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如何處理一個:許多和許多:許多關係。這裏的DDL SQLite的專家吐出來爲我的小數據庫:

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的專家說,他們是在和我在一個地方更改的數據,就像人的是PersonID它確實會更改Dog和GroupPersons表中的PersonID。我嘗試將數據庫重新添加到項目中,'運行自定義工具'以使.tt文件再次執行,甚至刪除它們並將它們添加回來。我可以得到一個簡單的項目來執行簡單的查詢和插入,但是我現在試着改變一個Person,Dog或Group和x.Save()的主鍵,但是System.Data.SQLite拋出了一個異常所有三個,在Save()上說SQLite error near "WHERE":syntax error.

對於我下一步應該嘗試做的任何建議?

+0

在'x.Save()'函數中使用的查詢是什麼? – MPelletier 2010-08-24 03:41:35

回答

5

看來,FKTables每個屬性表未在文件「SQLite.ttinclude」中分配。所以我添加了一些代碼行,並設法生成外鍵代碼:

第16行(var schema = conn。的getSchema( 「列」);),插入:

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

線後29(tbl.Name =行[ 「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); 
} 

和後(col.IsNullable =行[ 「IS_NULLABLE」]的ToString()== 「真」)線53,插入件:

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

這是爲生成外鍵碼。

此外,當您必須刪除一個列中有一列作爲另一個表中的外鍵的記錄時,您可能會遇到問題?例如: Person(Id,Name) Dog(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源代碼並編譯最新版本。它對我很好。

祝你好運。 對不起,我的英語:)

+0

你在SO上有一個好的開始! – MPelletier 2010-08-26 11:15:52

1

我想說明這一點。似乎就在眼前兩個問題:

  • 亞音速不承認你的外鍵
  • 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]));