我是否应该避免通过方法将UnitOfWork实例传递给策略?

时间:2013-01-11 17:53:49

标签: c# .net entity-framework design-patterns unit-of-work

想象一下,我有一个像下面这样的方法,它使用一些策略来创建新产品并在Db中将它们保留下来。

一切都是作为工作单元的一部分发生的。

(我的关注和)问题: 我担心将UnitOfWork实例作为参数传递给策略并在根方法中提交更改是可以或可以预防的吗? 如何避免将UnitOfWork实例作为参数传递给策略,但仍然使它们作为工作单元的一部分工作?

(我不喜欢有人可以通过错误调用策略实现中的.Commit这个事实 - 我不想要这样做。)

public void DoTheJob(CustomerRequest req)
{

 var materialsPikcerStrategyFactory = new PickerStrategyFactory();
 var productionStrategyFactory = new ProductionStrategyFactory();

 var materialsPickerStrategy = materialsPikcerStrategyFactory.GetStrategy(req); 
 var productionStrategy = productionStrategyFactory.GetStrategy(req);

 using (var uow = new UnitOfWorkFactory() )
 {
    var materials = materialsPickerStrategy.PickMaterials(req, uow);
    var products = productionStrategy.CreateProductsWith(materials, uow);
    uow.Commit();
 }

}


puplic abstract class MaterialsPickerStrategy 
{

 // Picks some material entities from Db and modifies some of its properties before usage
 public abstract ICollection<Material> PickMaterials(CustomerRequest req, IUnitOfWorkFactory uow);

}

public abstract class ProductionStrategy
{
 // Gets the materials and creates some new instances by ADD'ing them to the repository
 public abstract void CreateProductsWith (ICollection<Material> materials, IUnitOfWorkFactory uow);
}

2 个答案:

答案 0 :(得分:1)

我会将一个UnitOfWork作为依赖项传递给执行提交所需的任何类,在您的情况下,如果我明白,您不想成为您的策略。

UnitOfWork应该知道如何提交更新,因为它会引用某种数据上下文。也许和实体框架模型,DBContext等

如果不应该提交UnitOfWork,你的策略应该不知道。我猜你可能正在使用UnitOfWork将您的数据上下文暴露给您的策略。

您的策略和UnitOfWork都应该引用相同的数据上下文。然后你的策略使用上下文和其他一些例程,它可能已经使用了很多策略,会引用UnitOfWork来提交它。

如果您使用IOC框架,这一切都非常简单,因为您将数据上下文的生命周期范围指定为PerRequest,并且您将其作为依赖项传递给两个类。当框架将该依赖注入到您的类中时,它将使用相同的实例,因此您的策略将写入工作单元所持有的同一实例。通过这种方式,您通过策略对数据所做的更改与工作单元提交的更改相同。如果您真的很熟悉IOC,您实际上可以注入给定类所需的上下文的各个部分,从而进一步隔离依赖项。

答案 1 :(得分:1)

您的代码似乎只使用工作单元而不是存储库。它们通常一起用来解决您的问题。存储库负责从数据库中获取数据或注册当前工作单元中的更改,工作单元负责提交已注册的更改。这将允许您将存储库传递给您的策略和策略将无法访问工作单元。

就EF而言ObjectContext / DbContext可视为工作单元,ObjectSet / DbSet可视为存储库。如果您有自定义工作单元和自定义存储库,则它们必须共享单个EF上下文实例。