首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用事务还是使用SaveChanges(false)和AcceptAllChanges()?

使用事务还是使用SaveChanges(false)和AcceptAllChanges()?
EN

Stack Overflow用户
提问于 2009-05-02 20:50:03
回答 2查看 290.6K关注 0票数 359

我一直在调查事务,似乎只要我将false传递给SaveChanges(),然后在没有错误的情况下调用AcceptAllChanges(),它们就会在EF中自行处理:

代码语言:javascript
复制
SaveChanges(false);
// ...
AcceptAllChanges();

如果事情变坏了怎么办?我不需要回滚吗?或者,一旦我的方法超出作用域,事务就结束了吗?

事务中途分配的任何缩进列会发生什么情况?我假设如果其他人在我的记录之后添加了记录,而我的记录还没有坏,那么这意味着将会有一个丢失的标识值。

有什么理由在我的代码中使用标准的TransactionScope类吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-05-02 21:24:26

对于实体框架,大多数情况下SaveChanges()就足够了。这将创建一个事务,或在任何环境事务中登记,并在该事务中执行所有必要的工作。

不过,有时SaveChanges(false) + AcceptAllChanges()配对也很有用。

最有用的地方是在您想要跨两个不同上下文执行分布式事务的情况下。

例如,像这样(不好的):

代码语言:javascript
复制
using (TransactionScope scope = new TransactionScope())
{
    //Do something with context1
    //Do something with context2

    //Save and discard changes
    context1.SaveChanges();

    //Save and discard changes
    context2.SaveChanges();

    //if we get here things are looking good.
    scope.Complete();
}

如果context1.SaveChanges()成功,但context2.SaveChanges()失败,则整个分布式事务将中止。但不幸的是,实体框架已经丢弃了context1上的更改,因此您不能重放或有效地记录失败。

但如果您将代码更改为如下所示:

代码语言:javascript
复制
using (TransactionScope scope = new TransactionScope())
{
    //Do something with context1
    //Do something with context2

    //Save Changes but don't discard yet
    context1.SaveChanges(false);

    //Save Changes but don't discard yet
    context2.SaveChanges(false);

    //if we get here things are looking good.
    scope.Complete();
    context1.AcceptAllChanges();
    context2.AcceptAllChanges();

}

当对SaveChanges(false)的调用将必要的命令发送到数据库时,上下文本身不会改变,因此您可以在必要时再次执行此操作,或者您可以根据需要询问ObjectStateManager

这意味着如果事务实际上抛出了异常,您可以通过重试或在某个地方记录每个上下文ObjectStateManager的状态来进行补偿。

有关更多信息,请参阅my blog post

票数 465
EN

Stack Overflow用户

发布于 2015-03-06 10:19:32

因为某些数据库可能会在dbContextTransaction.Commit()抛出异常,所以最好这样做:

代码语言:javascript
复制
using (var context = new BloggingContext()) 
{ 
  using (var dbContextTransaction = context.Database.BeginTransaction()) 
  { 
    try 
    { 
      context.Database.ExecuteSqlCommand( 
          @"UPDATE Blogs SET Rating = 5" + 
              " WHERE Name LIKE '%Entity Framework%'" 
          ); 

      var query = context.Posts.Where(p => p.Blog.Rating >= 5); 
      foreach (var post in query) 
      { 
          post.Title += "[Cool Blog]"; 
      } 

      context.SaveChanges(false); 

      dbContextTransaction.Commit(); 

      context.AcceptAllChanges();
    } 
    catch (Exception) 
    { 
      dbContextTransaction.Rollback(); 
    } 
  } 
} 
票数 -6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/815586

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档