我正在用C#编写一个需要在多个表中插入数据的程序。第一个插入返回最后一个插入rowid,后者又用于在其他表上执行插入。在伪代码中:
INSERT INTO TableFoo (Col2, Col3, Col4, etc.) VALUES (@Bla2, @bla3, @bla4);
在此插入之后,我立即获得最后一个插入ID:
SELECT last_insert_rowid() AS RowId;
我在datareader中检索RowId列并将其存储在int“RowId”中。 最后,我插入了一些表格,如:
INSERT INTO TableBar (FooId, Col2) VALUES (RowId, @BSomeMoreBla)");
问题:如果可能的话,我想在1个事务中执行这一组插入(和一个select RowId)以防止一些半保存的数据。在这种情况下是否可以使用交易以及首选方式?
SQLite交易? C#的System.Transactions命名空间? 第三种执行原子数据库多插入的方法......?
答案 0 :(得分:4)
ryber在我的路上帮助了我,但我找到了我自己寻找的解决方案。对于那些可能感兴趣的人,这是我的代码(可能需要一点微调,但是完全合法且可用的代码):
NB。 tbl1具有自动递增PK,tbl2和tbl3通过FK依赖于tbl1的PK。 如果发生异常,则不提交任何查询,就像一个体面的事务应该表现一样;-)。只有在没有错误的情况下执行Commit()时,才会插入整个数组,即使在路中间有一个SELECT。
try {
transaction = connection.BeginTransaction();
command = new SQLiteCommand();
command.Transaction = transaction;
command.CommandText = "INSERT INTO tbl1 (data) VALUES ('blargh')";
command.ExecuteNonQuery();
command = new SQLiteCommand();
command.Transaction = transaction;
command.CommandText = "SELECT last_insert_rowid()";
rowId = Convert.ToInt64(command.ExecuteScalar());
command = new SQLiteCommand();
command.Transaction = transaction;
command.CommandText = "INSERT INTO tbl2 (id, tbl1Id) VALUES (2, @rowId)";
command.Parameters.Add(new SQLiteParameter("@rowId", rowId));
command.ExecuteNonQuery();
command = new SQLiteCommand();
command.Transaction = transaction;
command.CommandText = "INSERT INTO tbl3 (id, tbl1Id) VALUES (3, @rowId)";
command.Parameters.Add(new SQLiteParameter("@rowId", rowId));
command.ExecuteNonQuery();
transaction.Commit();
}
catch (Exception ex) {
if(connection.State == ConnectionState.Open)
transaction.Rollback();
MessageBox.Show(ex.Message);
}
finally {
connection.Close();
transaction.Dispose();
command.Dispose();
}
答案 1 :(得分:2)
它应该绝对是一个SQLite事务。你最好的选择是使用像这样的Sqlite数据提供者:http://sqlite.phxsoftware.com/我不确定它自己的基本ADO.Net是否真的能正常工作。
编辑评论:
好的,所以你只想像任何其他ADO交易那样进行交易:
SqliteCommand command = connection.CreateCommand();
SqlTransaction transaction = null;
connection.Open();
transaction = connection.BeginTransaction();
command.Transaction = transaction;
command.CommandText = "Insert bla";
command.ExecuteNonQuery();
command.CommandText = "Update bla";
command.ExecuteNonQuery();
transaction.Commit();
connection.Close();
您通常还希望将所有内容放在try / catch中并使用回滚
注意:我不是100%使用该SQlLite命令。看看你的文档......但其余的应该是正确的