![](/img/trans.png)
[英]C# Entity Framework Code-First- How do you add a row with foreign key using just the id of that foreign key?
[英]In c# compact-framework, how do you do a SQLite transaction while keeping foreign key constraints in an open connection?
我正在 Windows Forms .Net Compact Framework 3.5 中創建一個帶有 SQLite 數據庫的應用程序。 出於性能原因,我需要保持與數據庫的開放連接,並且我需要使用事務來執行多個更新以實現回滾的可能性。
在一些 SQLite 表中有外鍵約束,默認情況下外鍵強制是關閉的,所以我必須在打開從應用程序到數據庫的連接時手動打開它們。
現在的問題是事務不允許外鍵約束:( https://sqlite.org/pragma.html#pragma_foreign_keys )
因此,當我運行更新語句時,它們失敗並且事務回滾。
我嘗試在事務之前手動關閉外鍵約束,然后更新成功。 但是當我嘗試在事務后重新打開外鍵約束時,更新失敗。
我需要打開外鍵約束,但它們在事務期間失敗,我不能簡單地關閉它們,運行事務,然后再重新打開它們。 所以我該怎么做?
using (var cmd1 = new SQLiteCommand(Con))
{
cmd1.CommandText = "PRAGMA foreign_keys = 0"; //turn foreign key contraint off before transaction
cmd1.ExecuteNonQuery();
}
var cmd2 = new SQLiteCommand(Con);
using (SQLiteTransaction transaction = Con.BeginTransaction())
{
//run update commands here
transaction.Commit(); //run transaction
}
using (var cmd3 = new SQLiteCommand(Con))
{
cmd3.CommandText = "PRAGMA foreign_keys = 1"; //turn foreign key constraint back on after transaction
cmd3.ExecuteNonQuery(); //this doesnt work
}
您可以在事務期間啟用外鍵。 您不能在交易期間打開或關閉它們 - 您必須在開始交易之前打開它們。
當您打開連接時打開 pragma 可能是最簡單的 - 然后您可以忘記它。
這對我來說很好用:
// Con is a SQLite connection, that has been opened.
using (var cmd = Con.CreateCommand())
{
cmd.CommandText = "PRAGMA foreign_keys = ON";
cmd.ExecuteNonQuery();
}
using (var cmd = Con.CreateCommand())
{
cmd.CommandText = @"
CREATE TABLE A(id integer not null primary key);
CREATE TABLE B(id integer not null primary key, a_id integer, FOREIGN KEY(a_id) REFERENCES A(id))
";
cmd.ExecuteNonQuery();
}
try
{
using (var transaction = Con.BeginTransaction())
{
using (var cmd = Con.CreateCommand())
{
cmd.CommandText = "INSERT INTO A VALUES(1); INSERT INTO A VALUES(2); INSERT INTO B VALUES(1, NULL); INSERT INTO B VALUES(2, 1);";
cmd.ExecuteNonQuery();
}
using (var cmd = Con.CreateCommand())
{
cmd.CommandText = "INSERT INTO B VALUES(3, 55);";
cmd.ExecuteNonQuery(); //Will crash beceause of invalid reference
}
transaction.Commit();
}
} catch(DbException) {
// Ignore transaction failure in this example
if(!e.Message.Contains("foreign key constraint failed"))
throw;
}
using (var cmd = Con.CreateCommand())
{
// Validate that nothing was inserted in the failed transaction
cmd.CommandText = "SELECT COUNT(*) FROM A";
Debug.Assert((long)cmd.ExecuteScalar() == 0);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.