EntityFramework,服务和交易

时间:2018-03-12 10:43:26

标签: c# transactions entity-framework-6

我目前正在使用EF6和业务规则的服务模式。我需要交易。不幸的是,我对EF如何管理交易没有深入的了解。请看下面的代码:

public class Service1
{
    private DbContext context;
    private string connectionString = "yada, yada, yada";
    public Service1()
    {
        context = new DbContext(connectionString); //DbContext is IRL a 
        context from an EF-dbfirst project, this is only for illustration
    }

    public void SaveStuff(object stuff)
    {
        var transaction = context.Database.BeginTransaction();
        try
        {
            var s2 = new Service2();
            context.[DbEntity].Add(stuff);
            s2.SaveOtherStuff("stuff");
            context.SaveChanges();
            transaction.Commit();
        }
        catch
        {
            transaction.Rollback();
        }
    }
}

public class Service2
{
    private DbContext context;
    private string connectionString = "yada, yada, yada";
    public Service2()
    {
        context = new DbContext(connectionString);
    }

    public void SaveOtherStuff(object stuff)
    {
        context.[DbEntity].Add(stuff);
    }
}

使用Service1上下文对象创建事务。交易是否会跟随Service2或Service2使用上下文对象而不知道正在进行的事务?我是否需要以某种方式将拥有事务的上下文对象传递给Service2(构造函数)?

2 个答案:

答案 0 :(得分:0)

答案是否定的,这似乎都是一个糟糕的设计。

一些注释:您不应该真正创建并保留DbContextsTransactionsDisposed中的using都应该Transaction理想的陈述

但是,我相信你可以对多个DBContexts使用相同的using (TransactionScope scope = new TransactionScope()) { using (myContext context = new myContext()) { Test t = new Test() t.Name="TEST"; context.AddToTests(t); context.SaveChanges(); } using (myContext context = new myContext()) { Demo d = context.Demos.First(s => s.Name == "Demo1"); context.DeleteObject(d); context.SaveChanges(); } scope.Complete(); // also make sure you add error checking and rollback } ,但我认为这可能依赖于SqlServer版本,如果数据库存在于同一个SqlServer中,那么就不要引用我就是那个"

DBContext

最后,在不同的Service调用上使用相同的上下文似乎是错误的,您不需要缓存EFDBContext这项工作非常适合幕后工作

<强>更新

我刚注意到您为每项服务创建了一个新的using。无论如何,对DbContextTransaction使用PARAMETERS [Forms]![Reports Window]![cmb_ar] Long, [Forms]![Reports Window]![ar_frm_dt] DateTime, [Forms]![Reports Window]![ar_to_dt] DateTime; SELECT ITEM, [Transaction Date], ID, Reciept, Issued, Returns, Remarks, Manual FROM <snip> 语句或冒被同事诋毁的风险:)

答案 1 :(得分:0)

我不明白为什么你需要实例化两个dbcontext,但是如果你通过服务共享相同的dbcontext,你不需要使用显式事务(.SaveChanges()自己创建一个sql事务)然后将dbContext传递给构造函数中的Service2。

如果你想使用两个不同的dbContext,你只能共享事务和第一个dbContext的连接,那么:

public void SaveStuff(object stuff)
{
   using(var transaction = context.Database.BeginTransaction())
   {
        try
        {
            var s2 = new Service2(transaction, context.Database.Connection);
            context.[DbEntity].Add(stuff);
            s2.SaveOtherStuff("stuff");
            context.SaveChanges();
            transaction.Commit();
        }
        catch
        {
            transaction.Rollback();
        }
   }
}


public class Service2
{
    private DbContext context;
    public Service2(DbContextTransaction transaction, DbConnection connection)
    {
        context = new DbContext(connection, false);
        context.Database.UseTransaction(transaction);
    }

    public void SaveOtherStuff(object stuff)
    {
        context.[DbEntity].Add(stuff);
    }
}