C# 使用自定义UOW和ORM(EF6)的并行事务问题

C# 使用自定义UOW和ORM(EF6)的并行事务问题,c#,entity-framework,design-patterns,orm,repository-pattern,C#,Entity Framework,Design Patterns,Orm,Repository Pattern,有一点背景知识,我正试图实现通用存储库和UOW模式以及作为ORM的实体框架 1.开始换药。 2.通信传输 3.回滚事务 4.4保存更改 5.i导入 6.处置 public class UnitOfWork: IUnitOfWork { private DbTransaction transaction; private readonly DbContext context; public UnitOfWork(DBContext dbContext ) { context

有一点背景知识,我正试图实现通用存储库和UOW模式以及作为ORM的实体框架

1.开始换药。 2.通信传输 3.回滚事务 4.4保存更改 5.i导入 6.处置

public class UnitOfWork: IUnitOfWork
{
  private DbTransaction transaction;
  private readonly DbContext context;
  public UnitOfWork(DBContext dbContext )
  {
    context = dbContext ;
  }   
  public void Begintransaction()
  {
    transaction = context.Database.Connection.BeginTransaction(isolationLevel);
  }
  public void CommitTransaction()
  {
    context.SaveChanges();
    transaction.Commit();
    ReleaseCurrentTransaction();
  }
   ....
   ....
}
我的通用存储库类

public class Repository : IRepository
{
  private dbContext;
  protected DBContext Context
  {
     get
     {
       return dbContext != null? dbContext : dbContext = GetContextFromFactory();
     }
  }
  public void Add<T>(T entity)
  {
    dbContext.Set<T>.Add(entity);
  }
}
当我运行此代码来保存person对象时,它会在UOW的CommitTransaction()方法中的context.SaveChanges()上引发异常。 例外情况是“SqlConnection不支持并行事务”

  • 我是不是在代码中做错了什么
  • UOW中的交易存在一些问题
  • 不支持与ORM结合的UOW事务
  • 如果不支持事务,那么当DbContext或任何其他ORM默认实现unitofwork模式时,UnityOfWork模式的用途是什么
  • 我将感谢你的建议和评论

    [更新] 我已经修复了这个问题,通过创建上下文来接受当前已经存在的事务。我的修复程序在CommitTransaction()代码中。我需要您的评论

    从这个

      public void CommitTransaction()
      {
       context.SaveChanges();
        transaction.Commit();
        ReleaseCurrentTransaction();
      }
    
    对这个

     public void CommitTransaction()
      {
        context.UseTransaction(this.transaction);
        context.SaveChanges();
        transaction.Commit();
        ReleaseCurrentTransaction();
      }
    
    这种方法有什么缺点吗?请分享你的评论

  • DbContext不是线程安全的-不要跨线程使用DbContext
  • 连接字符串应确保连接允许MARS。见下文
  • UoW模式是ORM的最佳实践。由EF支持
  • EF框架为您管理事务。无需将事务处理添加到基本存储库类。
    添加对象1,更改对象2,删除对象3,
    然后保存更改。
    将由EF作为交易执行。没有脏的未提交的读取。 如果其中一个更新失败,将回滚更改
  • 通过消息队列的事务。 有关何时可能希望在EF中使用事务的常规信息

  • 尽快处理上下文实例。定期更新是一般建议

  • 连接字符串:请参阅MultipleActiveResultSets=true

     <connectionStrings>
        <add name="myConn" connectionString="Data Source=localhost;Initial Catalog=MyDbName ;Integrated Security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
    </connectionStrings>
    
    
    
    My DbContext作用域是web应用程序的每个HttpRequest,而windows则是共享静态上下文。这样行吗?请看我的更新,让我知道你的想法。我希望httpreq将工作。但不理解为什么要手动控制范围。它看起来像单个数据库存储库UoW更新。为什么不让EF来做呢。请注意windows应用程序中长期运行的静态上下文。您不能使用多线程,并且随着时间的推移可能会导致上下文膨胀。即使在windows应用程序中,也建议续订上下文。这样做很便宜。我不明白你的意思,但不明白你为什么要手动控制范围。我想应该是这样的,我不知道内置选项。可能是因为我试图遵循这种模式。请开导我。顺便说一句,我有一个使用存储库的Web服务和windows服务。目前我只有一个存储库。谢谢您的时间。尝试一个简单的测试。创建新的上下文。添加2条记录。确保其中一个将导致dup密钥或某些错误。保存更改。EF将回滚另一条记录。ef使用事务。这一切都是为了你。
     <connectionStrings>
        <add name="myConn" connectionString="Data Source=localhost;Initial Catalog=MyDbName ;Integrated Security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
    </connectionStrings>