【问题标题】:How can I implement UnitOfWork, Repository Pattern, Unity and EF with Thread Safe如何使用线程安全实现 UnitOfWork、存储库模式、Unity 和 EF
【发布时间】:2015-03-19 02:58:39
【问题描述】:

我在想这样的事情:

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”的实例,我可能需要在构造函数中进行解析...

我的另一种想法

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% 线程安全的,但我会缩短上下文实例

你有别的想法吗? 我现在要进行单元测试...

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

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

... save, delete, linq ...

oUoW.MutexUnlok();

mmm .... &%$··%&·!&$%&...mmm LAPSUS

【问题讨论】:

  • 你的申请是什么?网络服务 ?知道会很有用。您上面的消费代码是每个线程创建的吗?
  • 主题但为什么要在所有内容前加上'o'?除了它让你的代码在你大声朗读时听起来像鬼一样吗?

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


【解决方案1】:

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

【讨论】:

  • 不必如此。 UoW 已解析,uow 中的存储库不必解析。
【解决方案2】:

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

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

【讨论】:

  • 我不太同意。具体的 uow 类型意味着具体的存储库,因此如果您解析 uow,您实际上并不需要解析存储库。我相信您在这里试图滥用 DI,将过多的责任放入其中,并直接依赖它制作过多的组件。
  • 是的,我想是的,但是以单元测试为例,我会做两个 UoW ,这可能是个好主意,虽然不太灵活,如果我想更改一个 Repository 的实现,我需要更改 UoW 实现而不是组合根。发生这种情况还远吗,但可能……目前我遵循您的想法,谢谢
  • UOW 和存储库中的松散耦合是个好主意。正如 OP 所说,任何实现都会让你接触一个类,只是因为依赖项更改违反了 SOLID 规则。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    相关资源
    最近更新 更多