【问题标题】:Entity Framework transactions实体框架事务
【发布时间】:2014-07-20 19:00:42
【问题描述】:

在 Entity Framework 6 中使用(重用)事务的最佳方式是什么。 用例: 如果我们有两种方法

public decimal Withdraw(string accNum, decimal amount) 
{
    using (var db = new MyDbContext())
    {
        var query = from t in db.MoneyTransactions
                    where t.AccountNumber.Equals(accNum)
                    select t;
        MoneyTransaction mt = query.First();
        mt.Amount -= amount;
        db.SaveChanges();
    }
    return amount;
}

public void Put(string accNum, decimal amount)
{
    using (var db = new MyDbContext())
    {
        var query = from t in db.MoneyTransactions
                    where t.AccountNumber.Equals(accNum)
                    select t;
        MoneyTransaction mt = query.First();
        mt.Amount += amount;
        db.SaveChanges();
     }
}

我想单独使用这些方法(例如,将钱存入账户)并在单个交易中使用它们:

public void Transfer(string srcAcc, string destAcc, decimal amount) 
{
    Withdraw(srcAcc,amount);
    Put(destAcc,amount);
}

【问题讨论】:

    标签: c# .net entity-framework


    【解决方案1】:

    查看 Systems.Transactions 程序集和命名空间。 (BCL 的一部分)

    然后你可以这样做:

    using(var trans = new TransactionScope())
    {
        Withdraw(srcAcc, amount);        // No changes needed to these
        Put(destAcc, amount);            //   two methods...
    
        trans.Complete();
    }
    

    System.Transactions 将创建所谓的环境事务。这是存储在线程上的事务,任何 ADO.NET、LINQ-to-SQL 和 Entity Framework DB 操作都将使用查找此TransactionScope 对象。

    此事务在using 块的末尾提交或回滚。 在 TransactionScope 对象上调用 Complete() 将触发数据库中的提交,而不调用 Complete() 将改为回滚事务。

    【讨论】:

    • EF提供事务机制,纯db事务无需使用其他任何东西。
    • @Rodrigo:是的,而且 System.Transactions 使它更易于使用。您为什么不为此使用 System.Transactions?
    • 知道这段代码如何使用 async/await 吗?如果事务存储在线程中,这是一个相当有问题的范围......
    • @mot: 没试过,但是快速搜索会出现这个结果:stackoverflow.com/a/17527759/19594
    【解决方案2】:

    你可以使用重载方法:

    public void Put(string accNum, decimal amount, MyDbContext context)
    {
        var query = from t in context.MoneyTransactions
                    where t.AccountNumber.Equals(accNum)
                    select t;
        MoneyTransaction mt = query.First();
        mt.Amount += amount;
        db.SaveChanges();
    }
    
    public void Put(string accNum, decimal amount)
    {
        using (var db = new MyDbContext())
        {
            Put(accNum, amount, db);   
        }
    }
    

    Withdraw 方法相同。然后你可以写:

    using (var db = new MyDbContext())
    using (var tran = db.Database.BeginTransaction())
    {
        try
        {
            Withdraw(srcAcc, amount, db);
            Put(destAcc, amount, db);
    
            tran.Commit();
        }
        catch
        {
            tran.Rollback();
    
            throw;
        }
    }
    

    由于方法重载,您不必重构其他现有方法即可应用新参数 (MyDbContext)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 2017-01-06
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多