【发布时间】:2021-12-30 08:33:50
【问题描述】:
在我正在维护的项目中,我使用存储库模式重构了一些逻辑,而不是旧的 ORM (LinqToSql)。
我现在的问题是有时我必须跨存储库共享 DataContext(这是一个理想的功能),但这些存储库试图“窃取”彼此的加载选项。
这是我的存储库构造函数的示例,它接收 DataContext 并构建正确的加载选项。
public ArticleRepository(DataContext datacontext) : base(datacontext)
{
this.Name = "ArticleRepository";
lock ( _sync )
{
this.Datacontext = datacontext; // --> this is done in base class, assing the shared object to the current repository.
this.Datacontext.DeferredLoadingEnabled = false;
DataLoadOptions options = new DataLoadOptions();
options.LoadWith<tbl_ana_Article>(article => article.UoM);
options.LoadWith<tbl_ana_Article>(article => article.Brand);
this.Datacontext.LoadOptions = options;
}
}
但我也有 OrderRepository 它自己的加载选项。
当我在同一个 DataContext 上使用此类存储库时会出现问题:
using ( var context = new MyDatacontex("...") )
{
var articleRepo = new ArticleRepository(context);
var orderRepo = new OrderRepository(context);// <-- here the loading option are overwritten
articleRepo.DoStuff();
orderRepo.DoOtherStuff();
context.SubmitChanges();
}
现在在这种特定情况下,我可以重新排序操作并避免出现问题,但这是一个非常具体且脆弱的解决方案。
我不知道是否必须在构造函数中指定加载选项,将其保存在对象中,并在每次使用(读取)数据上下文之前覆盖共享数据上下文属性。这是一个好的解决方案还是有更好的解决方案?
【问题讨论】:
-
你有这样的麻烦应该告诉你你使用了错误的模式。该 DataContext 已经是一个工作单元,每个实体类型都有一个存储库成员。它缓存所有实体的所有更改,并在调用
SubmityChanges时将它们持久化。另一方面,LInq-to-SQL 不仅仅是旧的,它从来都不是一个功能齐全的 ORM。它很快被实体框架取代 -
those repository try to "steal" each other the loading option.这些不是彼此的选择。它们适用于整个 DataContext。您正在尝试将低级别的单实体存储库包装器放在更高级别的多实体 DataContext 上。 DataContext 实例表示单个事务,仅加载和修改特定用例所需的实体。它不是整个数据库的模型,不应该尝试映射所有表。它只需要映射其特定用例所需的表。拥有不同实体的多个上下文非常好 -
@PanagiotisKanavos:如果我不理解,问题是我不应该有“共享边界”。每个域都有自己的存储库,具有自己的数据上下文,并且它们从不共享任何内容。问题是在我的场景中如此严格的建模风险(恕我直言)成本太高,所以我放松了一点。在某些情况下(像这样),处理运输的域必须与处理文章的域一起工作,因此它们可以一起工作,原子。让我知道我的图片是否有问题。再次感谢您的帮助,并为我的英语(不是母语)道歉
-
错了。这里的域存储库是 DataContext 本身。如果您想使用领域驱动设计,DataContext 用于将实体持久保存在有界上下文中,用于加载聚合根。如果要抽象 DataContext,则需要创建一个存储库来处理整个有界上下文,而不是单个实体
-
@PanagiotisKanavos 啊..所以我有点失落抱歉。在我的想法中,我有许多 linq2sql 模型,每个域一个。文章和订单应该分开,但因为有时他们需要合作,我选择将它们放在同一个数据上下文中,即使它们有两个不同的存储库。通常文章和订单的存储库单独工作,但在需要时它们会合作(如在上传的代码中)。那时在我看来,将数据上下文视为域是一个好主意,因此我可以将加载选项都放在这个特定的数据上下文工厂中
标签: c# linq-to-sql datacontext