我正在使用SQLite(v1.0.88.0)和Dapper通過額外的閉包表來存儲一些分層數據。我已經在SQLite中啓用了foreign_keys
支持,但它對我完全不起作用。
下面是一個說明了幾個問題,我最小的示例代碼:外鍵約束問題(分層數據)
using System.Data.SQLite;
using System.IO;
using Dapper;
class Program {
static string db = "test.db";
static void Main(string[] args) {
if(!File.Exists(db))
SQLiteConnection.CreateFile(db);
using(SQLiteConnection c = new SQLiteConnection("Data Source=" + db)) {
string initializationQuery =
"PRAGMA foreign_keys = ON;" + // enable FK
"DROP TABLE IF EXISTS Departments;" +
"DROP TABLE IF EXISTS Departments_treePath;" +
"CREATE TABLE IF NOT EXISTS Departments (ID INTEGER PRIMARY KEY AUTOINCREMENT, Name TEXT);" +
"CREATE TABLE IF NOT EXISTS Departments_treePath (ancestor INTEGER, descendant INTEGER, level INTEGER, " +
"PRIMARY KEY (ancestor, descendant)," +
"CONSTRAINT ancestor_ref FOREIGN KEY(ancestor) REFERENCES Departments(ID) ON DELETE CASCADE," +
"CONSTRAINT descendant_ref FOREIGN KEY(descendant) REFERENCES Departments(ID) ON DELETE CASCADE);";
c.Execute(initializationQuery);
long idA = AddNode(c, 0, "A"); // ID=1
long idB = AddNode(c, idA, "B"); // ID=2
long idC = AddNode(c, idB, "C"); // ID=3
// 1) It works , but it should not, because there is no ID=7 (FK fails)
c.Execute("INSERT INTO Departments_treePath (ancestor,descendant) VALUES (7,7)");
// 2) It works, but as far as i can see from SQLite DataBase Browser it does not delete all the references within the Departments_treePath table (cascade delete fails)
c.Execute("DELETE FROM Departments WHERE [email protected];", new { id = idC });
}
}
static long AddNode(SQLiteConnection c, long ancestorID, string name) {
string query = "BEGIN;" +
"INSERT OR ROLLBACK INTO Departments (Name) VALUES(@Name);" +
"CREATE TEMP TABLE _ID AS SELECT last_insert_rowid() AS id;" +
"INSERT INTO Departments_treePath (ancestor, descendant, level) " +
"SELECT t.ancestor, (SELECT id FROM _ID), t.level + 1 FROM Departments_treePath AS t " +
"WHERE t.descendant = @ancestor " +
"UNION ALL SELECT id , id, 0 FROM _ID;" +
"SELECT id FROM _ID; DROP TABLE _ID;" +
"END;";
return System.Linq.Enumerable.First(c.Query<long>(query, new { ancestor = ancestorID, Name = name }));
}
}
我在SQL/SQLite的新的,似乎我已經失去了一些東西。請指導我。
對我的作品(在命令行上)。你確定'Execute'或'Query'可以執行多個語句嗎? –
感謝您的參與。是的,他們可以執行多個語句,因爲它只是包裝標準的dbconnection功能。 – DmitryG