C# 我是否应该也可以避免通过方法将UnitOfWork实例传递给策略?
想象一下,我有一种方法,如下面所示,它使用一些策略来创建新产品,并将它们作为结果保存在数据库中 每件事都是作为一个工作单元的一部分发生的 (我的担忧和)问题: 我关心的是,将UnitOfWork实例作为参数传递给strategies并提交根方法中的更改是否可以或可以预防? 如何避免将UnitOfWork实例作为参数传递给策略,但仍然使它们作为工作单元的一部分工作 (我不喜欢有人会错误地调用.Commit内部策略实现——我不希望这样)C# 我是否应该也可以避免通过方法将UnitOfWork实例传递给策略?,c#,.net,entity-framework,design-patterns,unit-of-work,C#,.net,Entity Framework,Design Patterns,Unit Of Work,想象一下,我有一种方法,如下面所示,它使用一些策略来创建新产品,并将它们作为结果保存在数据库中 每件事都是作为一个工作单元的一部分发生的 (我的担忧和)问题: 我关心的是,将UnitOfWork实例作为参数传递给strategies并提交根方法中的更改是否可以或可以预防? 如何避免将UnitOfWork实例作为参数传递给策略,但仍然使它们作为工作单元的一部分工作 (我不喜欢有人会错误地调用.Commit内部策略实现——我不希望这样) public void DoTheJob(CustomerRe
public void DoTheJob(CustomerRequest请求)
{
var materialsPikcerStrategyFactory=新PickerStrategyFactory();
var productionStrategyFactory=新的productionStrategyFactory();
var materialsPickerStrategy=materialsPikcerStrategyFactory.GetStrategy(需求);
var productionStrategy=productionStrategyFactory.GetStrategy(req);
使用(var uow=new UnitOfWorkFactory())
{
var物料=物料分拣策略分拣物料(需求,uow);
var products=productionStrategy.CreateProductsWith(物料,uow);
提交();
}
}
puplic抽象类MaterialsPickerStrategy
{
//从Db中拾取一些材质实体,并在使用前修改其某些属性
公共摘要I收集材料(客户请求,IUnitOfWorkFactory uow);
}
公共抽象类生成策略
{
//获取材质并通过将其添加到存储库来创建一些新实例
创建产品的公开摘要无效(i收集材料,i工厂uow);
}
我会将一个UnitOfWork作为依赖项传递给执行提交所需的任何类,我理解,在您的情况下,如果您不想成为您的策略的话
UnitOfWork应该知道如何提交更新,因为它会引用某种数据上下文。可能还有实体框架模型、DBContext等
如果你的策略不应该承诺,你就不应该知道工作单元。我猜您可能使用UnitOfWork将您的数据上下文公开给您的策略
您的策略和UnitOfWork都应该引用相同的数据上下文。然后,您的策略与上下文和其他一些例程一起工作,它可能使用了许多策略,最后会引用UnitOfWork来提交它
如果您使用的是IOC框架,这是非常直接的,因为您将数据上下文的生存期范围指定为PerRequest,并将其作为依赖项传递给两个类。当框架将依赖注入到类中时,它将使用相同的实例,因此您的策略将写入工作单元持有的相同实例。通过这种方式,您通过策略对数据所做的更改与工作单元将要提交的更改相同。如果你对IOC非常熟练,你实际上可以注入给定类所需的上下文的各个部分,进一步隔离依赖关系。你的代码似乎只使用工作单元,而不使用存储库。它们通常一起用来解决你的问题。存储库负责从数据库获取数据或注册当前工作单元中的更改,而工作单元负责提交已注册的更改。这将允许您将存储库传递给策略,而策略将无法访问工作单元
就EF而言,
ObjectContext
/DbContext
可以被视为工作单元,ObjectSet
/DbSet
可以被视为存储库。如果您有自定义工作单元和自定义存储库,它们必须共享单个EF上下文实例 因此,我可以传递存储库,这些存储库是我使用的UnitOfWork的属性,而不是paassing UnitOfWork。比如uow.MaterialsRepository
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);
}