C# 存储库和持久性

C# 存储库和持久性,c#,repository,C#,Repository,这就是我要做的 我有一个通用存储库类Repository。它具有常用的存储库模式方法 每个存储库在其构造函数中采用一个IContext,该构造函数为存储库提供持久性 我有专门的存储库,这些存储库由一个通用存储库组成,然后根据特定于专门对象的存储库操作定制方法。所以,如果我有一个专门的小猫对象存储库,它会有爬树的方法(可能是拿一个树对象),但不会有一个BuryBone(骨头)方法。我说得很糟糕的一点是,它在小猫和它的树之间建立了一种需要持续的联系void cleanswitters()可能是一个更

这就是我要做的

我有一个通用存储库类
Repository
。它具有常用的存储库模式方法

每个存储库在其构造函数中采用一个
IContext
,该构造函数为存储库提供持久性

我有专门的存储库,这些存储库由一个通用存储库组成,然后根据特定于专门对象的存储库操作定制方法。所以,如果我有一个专门的小猫对象存储库,它会有爬树的方法(可能是拿一个树对象),但不会有一个BuryBone(骨头)方法。我说得很糟糕的一点是,它在小猫和它的树之间建立了一种需要持续的联系
void cleanswitters()
可能是一个更简单的例子。这使小猫的胡须变得干净

所以我现在正在考虑一个相关子对象持久化的方案,并开始怀疑我是否已经犯了一点错误

我从存储库中创建子对象的稍微丑陋的方法开始。因此,Kitten存储库将有一个方法
CreateFurBall()
,该方法将向Kitten的FurBall集合中添加一个FurBall对象,并向FurBall存储库中添加一个要持久化的FurBall(实际上是同一个对象)

我现在改成了一个系统,在这个系统中,我有一个类似于ObservableCollection的东西,它在添加POCO时通知其父存储库。因此,我可以创建一个POCO furball并将其添加到集合中,然后该集合将自动注册到furball存储库中


首先,我将在上下文中实现nHibernate,我认为它映射得相当好。这是一个非常开放的问题,对于任何以前走过这条路线的人来说,你能看到什么让你“停下来!!”

我应该认为像爬树()、布里伯恩()、CreateFurBall()和CleanWhiskers()这样的方法属于域对象,而不是存储库

存储库应该处理聚合根的持久性,即允许您查询、保存和更新小猫。
在实例化和持久化之间,您想对小猫做的任何事情都是域的特权。

我过去使用存储库模式的方式,只是作为持久性提供程序和数据对象之间的一个非常薄的中介-每个存储库只包含非常通用的方法(即通常添加/更新/删除).

我认为您场景中的业务逻辑,即
CreateFurBall()
应该是使用存储库,而不是它公开的方法。

Nelson是正确的

我认为这两种制造Furball的方法可能存在混淆。如果一只小猫在数据库中存储了三个furball,那么当它从数据库中取出时,应该向小猫注入他的furball数据,并根据furball数据初始化furball集合

当应用程序希望向小猫添加furball时,小猫应通过
kitten.CreateFurBall()
发送furball。我在这里做的假设是,一个皮球是属于小猫的,而皮球对其他小猫来说并不常见。如果furball足够复杂,那么您可能需要将furball的创建抽象为一个furball工厂,小猫可以懒洋洋地引用该工厂

就小猫实体的创建而言,最好的处理方法可能是在您的KittenRepository中引用一个KittenFactory,它接受小猫的dto并从中构建小猫


您已经演示的最大问题是Kitten.BuryBone(骨骼)方法。小猫不埋骨头。狗会的。

我可能有点离题了,但我只是想对存储库模式说两句

存储库模式非常好,尤其是当您将它们都放在接口后面以便可以轻松地交换时。我为每个实体创建一个存储库。BrokenGlass是正确的,因为这些方法通常非常通用,并且不包含太多持久性逻辑之外的内容。我通常对将其放入存储库的逻辑类型不那么严格。例如,有些人认为将分页逻辑放入存储库是有罪的,但我不同意

我经常使用实体框架和LINQ来编写SQL。为了对这些结果进行分页,我需要LINQ在
IQueryable
上进行操作,以便在数据库级别进行分页。我不喜欢将
IQueryable
暴露在我的存储库之外。因为如果有一天我的存储库需要重写,而数据存储无法再使用
IQueryable
,该怎么办?因此,与其从我的存储库中返回,不如:

IQueryable<entity> GetEntities();
IQueryable GetEntities();
…并在控制器或应用程序的其他位置分页结果。相反,我这样做:

IEnumerable<entity> GetEntities_byPage(int page);
IEnumerable GetEntities_byPage(int page);
…我在存储库中执行分页逻辑,以便在数据源将其转换为表达式


我认为您的存储库应该返回一些相当定制的数据,而不仅仅是控制器必须清理的原始数据转储(通常是在首先将所有数据加载到内存之后,是的!)。

非常好的评论,谢谢。是的,BuryBone是一个小狗手术。我认为我的示例有点不恰当,专门的存储库将只负责持久化对象,但会强制执行某些限制。因此,如果我删除小猫,它将删除它的相关数据,furball和其他存储库中的所有数据。现在我的脑子里越来越清楚了。是的,听起来你明白了。有趣的是,我读了一篇关于在存储库中公开IQueryable的利弊的博客文章。反对的论点是,它混合了担忧,而专业人士则认为,它非常有用。我现在正在考虑支持它,我只需要想办法