[英]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.