如何使用线程安全实现 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 中是暂时的,谁能帮忙提供永久模板,谢谢!
我在想这样的事情:
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 中是暂时的,谁能帮忙提供永久模板,谢谢!