如何使用线程安全实现UnitOfWork,Repository Pattern,Unity和EF

时间:2015-03-19 02:58:40

标签: c# multithreading entity-framework unity-container unit-of-work

我在想这样的事情:

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 ....&amp;%$··%&amp;·!&amp; $%&amp; ... mmm LAPSUS

3 个答案:

答案 0 :(得分:0)

一旦你的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;
         }

答案 1 :(得分:0)

@Wiktor Zychla是对的,但我的示例实现可能会让您感到困惑。如果你正在使用像DI这样的DI容器,当UOW解决时,应该在UOW中注入存储库;并在UOW中注入一个DBContext实例(调用saveChanges)并在所有repositores中解析(我假设你的UOW有多个存储库,如果没有,你不需要UOW)。这被称为&#34;级联注射&#34;并且是使用DI容器的黄油和面包。

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

答案 2 :(得分:0)

好吧,我已经编辑了一个自动生成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中是时间性的,任何人都可以帮助永久模板,谢谢!