如何使用线程安全实现 UnitOfWork、存储库模式、Unity 和 EF

How can I implement UnitOfWork, Repository Pattern, Unity and EF with Thread Safe

我在想这样的事情:

IUoW oUoW = oUnity.Resolve<IUoW>(); //<-- New Context here (Life per resolve).
var oNewEntity = new SomeEntity{ name = "somethink ... "};

oUoW.oSomeEntity.Add( oNewEntity);
oUoW.SaveChanges();

oUoW.Dispose();//<-- delete context.

但是我如何解析 "oUoW.oSomeEntity" 的实例,我可能需要在构造函数中执行 Resolve 或不...

我在想的另一种方式

IUoW oUoW = oUnity.Resolve<IUoW>(); //<-- New Context here (Life per resolve).
var oNewEntity = new SomeEntity{ name = "somethink ... "};

oSomeEntityRepository = oUnity.Resolve<ISomeEntityRepository>();//Ugly way
oSomeEntityRepository.oUoW = oUoW;//Ugly way

oSomeEntityRepository.Add( oNewEntity);
oUoW.SaveChanges();

oUoW.Dispose();//<-- Delete context.

... Open Another Context ...

那段代码不是 100% 线程安全的,但我会缩短上下文实例

你有别的想法吗? 我现在就做单元测试...

为了线程安全,我正在考虑另一种使用 Mutex 的方法...类似...

IUoW oUoW = oUnity.Resolve<IUoW>();
oUoW.MutexLock();

... save, delete, linq ...

oUoW.MutexUnlok();

mmm ....&%$··%&·!&$%&...mmm 拉普萨斯

一旦你解决了你的 uow,存储库应该是 uow 的直接属性:

IUoW oUoW = oUnity.Resolve<IUoW>(); //<-- New Context here (Life per resolve).
var oNewEntity = new SomeEntity{ name = "somethink ... "};

oSomeEntityRepository = uow.SomeEntityRepository;//Not ugly at all

由于大多数示例实现都遵循这个想法,我想知道您的实现是什么。

总之就是这样

public class UnitOfWork
{
     private ISomeEntityRepository _someEntityRepository;
     public ISomeEntityRepository SomeEntityRepository
     {
         get
         {
              if ( _someEntityRepository == null )
                    _someEntityRepository = new ...
              return _someEntityRepository;
         }

@Wiktor Zychla 是对的,但他的示例实现可能会让您感到困惑。如果您使用的是 DI 容器,例如此处的 Unity,则应在解析 UOW 时将存储库注入 UOW;并且在 UOW 中注入单个 DBContext 实例(调用 saveChanges)并在所有存储库中解析(我假设你的 UOW 有多个存储库,因为如果没有,你不需要 UOW)。这被称为 "cascade injection" 并且是使用 DI 容器的黄油和面包。

通过这种方式,您可以使用多个存储库(一个用于聚合根)在数据库中进行多项更改来完成一个用例,并且只需要一个 UOW.Savechanges。

好吧,我已经编辑了一个自动生成 UnitOfWork、Context、Repository 和 FactoryUnitOfWork 的模板 http://pastebin.com/6D2X5Ykp,如果您在单独的文件中执行此操作,则需要编辑模板以更改实体模型dll.

要使用模式: 在 Composition Root 中注册:

IUnityContainer uc = new UnityContainer();
yourdaonamespace.CompositionRoot.Init( uc );

并使用:

using (var oIUoW = this.IFactoryUnitOfWork.Resolve())
{
    var YOURENTITYFoundedFromRepository = oIUoW.oRepositoryENTITY.First(o => o.iYourProperty == 1);
}

//more code 
using (var oIUoW = this.IFactoryUnitOfWork.Resolve())
{ 
   var entity = new domain.YOURENTITY()
   {
       sYourProperty = "TEST ENTITY"
   };
   uow.oRepositoryYOURENTITY.Insert(entity);
   uow.Commit();
}

要求:您需要生成 YOURMODEL.edmx

注意:模板在 Pastebin 中是暂时的,谁能帮忙提供永久模板,谢谢!