如何使用Entity Framework对象上下文执行事务?

时间:2011-03-07 17:11:12

标签: c# entity-framework transactionscope

我使用Entity Framework 4创建了一个非常简单的数据库。我希望能够在实体上使用事务,但我似乎无法保持回滚的变化。我真的只需要在将实体保存到数据库之前放弃对实体的临时更改。

例如,以下代码使用实体框架对象上下文“MusicContainer”。在TransactionScope中,创建了一个Artist实体。然后交易结束而没有完成;所以我希望这个交易可以回滚。但是,程序运行就像我从未创建过TransactionScope一样;在TransactionScope结束后,music.SaveChanges()行将对象保存到数据库。

class Program
{
    static void Main(string[] args)
    {
        using (MusicContainer music = new MusicContainer())
        {
            using (TransactionScope transaction = new TransactionScope())
            {
                Artist artist = new Artist { Name = "Test" };
                music.Artists.AddObject(artist);
            }
            // The transaction ended without Complete(); shouldn't the changes be abandoned?
            music.SaveChanges();
        }
    }
}

如果实体框架没有像我期望的那样使用TransactionScope,我怎样才能获得我正在寻找的功能?我有几种情况,函数的调用者在MusicContainer中传递,我需要在从函数返回之前将MusicContainer保持在干净状态(即回滚更改,以便他们不会意外地保存在另一个调用的SaveChanges中在同一个MusicContainer对象上。)

3 个答案:

答案 0 :(得分:7)

在这种情况下,您根本不需要TransactionScope,只需要SaveChanges() - 如果您有另一个using阻止MusicContainer,这将是在单独的事务中,不会保存当前using块中的任何更改。只有跨越多个DB上下文的事务才需要TransactionScope

一般情况下,上下文仅应用于由相关操作组成的工作单元,一旦完成调用SaveChanges()。为每个单独的,不相关的工作单元打开一个新的上下文。话虽如此,只需在你的场景中使用它:

        using (MusicContainer music = new MusicContainer())
        {
                Artist artist = new Artist { Name = "Test" };
                music.Artists.AddObject(artist);
                music.SaveChanges();
        }

答案 1 :(得分:2)

你的SaveChanges在错误的地方。

class Program
{
    static void Main(string[] args)
    {
        using (MusicContainer music = new MusicContainer())
        {
            using (TransactionScope transaction = new TransactionScope())
            {
                Artist artist = new Artist { Name = "Test" };
                music.Artists.AddObject(artist);
                music.SaveChanges();
            }
            // The transaction ended without Complete(); the changes are abandoned?
        }
    }
}

如果交易失败,您不应重复使用MusicContainer。为每个Unit of Work

创建一个新的

答案 2 :(得分:0)

实体框架应该能够使用 TransactionScope 。如果需要回滚仅通过此方法使用的更改,则需要启动New TransactionScope。

 using (MusicContainer music = new MusicContainer())
   {
     using (TransactionScope transaction = new TransactionScope(TransactionScopeOptions.RequiresNew))
          {
              Artist artist = new Artist { Name = "Test" };
              music.Artists.AddObject(artist);
              music.SaveChanges();
              scope.Complete(); 
          }
    }