我有两张桌子。第一个表包含一些数据。第二个表包含数据更改的历史记录。第一个表还包含引用上一个历史记录行的列。当第一个表中的行数据被更改时,复制将插入第二个表中,并在第一个列中更新引用最后一个数据副本的列。为此,我使用此代码
using (TransactionScope trn = new TransactionScope())
{
Table1 t1=model.Table1.Where(t=>t==id).FirstOrDefault();
/*update Table1 data*/
Table2 t2=new Table2();
t2.Table1=t1;
model.AddToTable2(t2);
/*set Table2 fields*/
model.SaveChanges();
t1.ref=t2.id;
model.SaveChanges();
trn.Complete();
}
使用TransactionScope保存符合数据是否严格?或者我需要使用其他方法?
答案 0 :(得分:1)
您需要保存两次更改吗?如果表是相关的,您应该能够设置导航属性并仅保存所有更改一次。在这种情况下,您不需要自己创建一个事务 - EF会为您创建一个事务。如果您需要保存两次更改,则TransactionScope应该可以解决问题。打开时,该连接将登记到事务中。在代码片段中,您不会显示您的上下文是如何实例化的,以及连接在进入事务之前会发生什么,因此很难判断它是否正确。
答案 1 :(得分:-1)
Context类默认支持事务。但是对于每个新的上下文类实例,都会创建一个新的事务。这个新事务是一个嵌套事务,一旦调用相关上下文类的SaveChanges(),它就会被提交。
在这种情况下,我们甚至不需要TransactionScope。我们可以简单地检查两个操作的结果,如果它们成功,我们只需要调用SaveChanges()方法。
当我们将ADO.NET调用与Entity框架混合时,通常需要TransactionScope。在这种情况下使用TransactionScope的技巧是让上下文类知道您想要将它与您自己的事务一起使用。由于事务与作用域中的连接对象相关联,因此我们需要将上下文类与与事务作用域关联的连接一起使用。此外,我们需要让上下文类知道它不能拥有连接,因为它是由调用代码拥有的。所以我们可以这样做:
using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
using (var conn = new SqlConnection("..."))
{
conn.Open();
var sqlCommand = new SqlCommand();
sqlCommand.Connection = conn;
sqlCommand.CommandText =
@"UPDATE Blogs SET Rating = 5" +
" WHERE Name LIKE '%Entity Framework%'";
sqlCommand.ExecuteNonQuery();
using (var context =
new BloggingContext(conn, contextOwnsConnection: false))
{
var query = context.Posts.Where(p => p.Blog.Rating > 5);
foreach (var post in query)
{
post.Title += "[Cool Blog]";
}
context.SaveChanges();
}
}
scope.Complete();
}