当前位置: 首页 > 编程语言 > C#

没有ORM的存储库模式分享

时间:2023-04-10 16:34:44 C#

C#学习教程:没有ORM的存储库模式但是,我遇到的问题是如何填充实体的一对多列表属性。例如,如果客户有一个订单列表,即如果Customer类有一个名为Orders的List属性,而我的存储库有一个名为GetCustomerById的方法,那么呢?这也回避了更改跟踪、删除等功能的问题?所以我认为最终的结果是我可以在没有ORM的情况下做DDD吗?但是现在我只对域实体中的延迟加载列表属性感兴趣?有任何想法吗?Nabil,我假设这对于那些没有在领域驱动设计中使用过ORM的人来说是一个非常普遍的问题?有任何想法吗?我可以在没有ORM的情况下进行DDD吗?是的,但是ORM简化了事情。老实说,我不认为你的问题与你是否需要ORM有任何关系——这是你对数据而不是行为的思考太多,这是DDD成功的关键。就数据模型而言,大多数实体将以某种形式与大多数其他实体相关,从这个角度来看,您可以遍历整个模型。这就是您的客户和订单的样子,也是您认为需要延迟加载的原因。但是您需要使用聚合将这些关系分解为行为组。例如,为什么要将客户聚合建模为具有订单列表?如果答案是“因为客户可以订购”,那么我不确定您是否处于DDD思维模式。什么行为需要客户端有订单列表?当你更多地考虑域的行为时(即,哪里需要什么数据),你可以根据用例对事物进行建模,事情变得更加清晰和简单,因为你只需要改变边界。我怀疑Customer应该是一个没有订单列表的单独聚合,而Order应该是一个包含订单行列表的聚合。如果您需要对客户的每个订单执行操作,请使用orderRepository.GetOrdersForCustomer(customerID);进行更改,然后使用orderRepository.Save(order);关于没有ORM的更改跟踪,有多种方法可以做到这一点,例如,订单聚合可能会引发一个事件,即订单存储库正在侦听已删除的订单行。当工作单元完成时,可以删除这些。或者稍微不那么优雅的方法是维护一个已删除的列表,order.DeletedOrderLines您的存储库显然可以读取这些列表。总结一下:根据评论进行编辑:我不认为我会为订单行实施延迟加载。您可以在没有订单行的情况下对订单执行哪些操作?我怀疑不多。但是,当DDD的“规则”似乎没有意义时,我并不是受其约束的人,??所以......如果在不太可能发生的情况下对订单对象执行了许多操作,则没有必要填充订单行,通常会有大量与订单相关的订单行(两者对我来说都一定是个问题)然后我会这样做:在订单对象中有这个私有字段:privateFunc>_lazilyGetOrderLines;订单存储库将在将其传递给订单时创建:Orderorder=newOrder(this.GetOrderLines);这是OrderRepository上的私有方法:privateIListGetOrderLines(GuidorderId){//DAL代码在这里}然后在orderlines属性中可能如下所示:publicIEnumberableOrderLines{get{if(_orderLines==null)_orderLines=_lazilyGetOrderLines(this.OrderId);返回_orderLines;编辑2我发现这篇博文与我的解决方案类似但更优雅:http://thinkbeforecoding.com/post/2009/02/07/Lazy-load-and-persistence-ignorance1)我应该加载GetCustomerById方法中的订单列表?将订单映射代码与客户映射代码分开可能是个好主意。如果您手动编写数据访问代码,则从GetCustomerById方法调用该映射模块是最佳选择。2)如果订单本身有另一个列表属性等等怎么办?将它们组合在一起的逻辑必须存在于某个地方;相关的聚合存储库与任何存储库一样好。3)如果我想做延迟加载怎么办?在哪里将代码加载到客户的订单属性中?在Orders属性中获取{}访问器?但是我必须将存储库注入域实体?我认为这不是正确的解决方案。我见过的最好的解决方案是让您的存储库返回子类域实体(使用类似CastleDynamicProxy的东西)——这让您对域模型的持久性一无所知。另一个可能的答案是创建一个从Customerinheritance继承的新Proxy对象,将其命名为CustomerProxy,并在那里处理延迟加载。所有这些都是伪代码,因此它为您提供了一个想法,而不仅仅是复制和粘贴以供使用。示例:publicclassCustomer{publicid{get;设置;}公共名称{get;设置;}等...公共虚拟IList订单{get;protectedset;}}这里是客户“代理”类......这个类不在业务层,但与上下文和数据映射器一起存在于数据层。请注意,您想要延迟加载的任何集合都应声明为虚拟(我相信EF4.0还要求您也将props设为虚拟,就像在纯POCO上运行时旋转代理类一样,以便Context可以跟踪更改)internalsealed类CustomerProxy:Customer{privatebool_ordersLoaded=false;publicoverrideIListOrders{get{IListorders=newList();if(!_ordersLoaded){//假设您正在使用映射器将实体转换为数据库并返回//映射器也存在于数据层中CustomerDataMappermapper=newCustomerDataMapper();orders=mapper.GetOrdersByCustomerID(this.ID);_ordersLoaded=真;//缓存Cases以便稍后使用实例base.Orders=orders;}else{订单=base.Orders;}退货单;因此,在这种情况下,我们的实体对象Customer仍然没有数据库/数据映射代码调用,这正是我们想要的……“纯”POCO。您已将延迟加载委托给存在于数据层中的代理对象,并实例化数据映射器并调用它。这种方法的缺点是调用客户端代码无法覆盖延迟加载……它可以打开或关闭。因此,在您的特定使用环境中,这取决于您。如果您知道75%的时间您总是需要客户的订单,那么延迟加载可能不是最佳选择。CustomerDataMapper最好在获取Customer实体时填充集合。同样,我认为NHibernate和EF4.0都允许您在运行时更改延迟加载特性,因此按照惯例使用ORM是有意义的,因为它为您提供了很多功能。如果您不经常使用Orders,请使用延迟加载来填充Orders集合。我希望这是“正确的”并且是一种为域模型设计实现延迟加载的正确方法。我对这个东西还是很陌生...麦克风以上就是C#学习教程:无ORM仓库模式分享的全部内容。收藏不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: