在阅读了Evan和Nilsson的书之后,我仍然不确定如何在域驱动的项目中管理数据访问。 如果CRUD方法是存储库的一部分,即OrderRepository.GetOrdersByCustomer(客户),或者它们应该是实体的一部分:Customer.GetOrders()。 后一种方法似乎更多OO,但它将在多个对象之间为单个实体类型分发数据访问,即Customer.GetOrders(),Invoice.GetOrders(),ShipmentBatch.GetOrders()等。 那么插入和更新呢?

===============>>#1 票数:15 已采纳

CRUD-ish方法应该是Repository ... ish的一部分。 但我想你应该问为什么你有一堆CRUD方法。 他们到底做什么? 他们是真正的? 如果您确实调出了应用程序使用的数据访问模式,我认为这会使存储库变得更有用,并且当您的域中发生某些类型的更改时,您将不必执行鸟枪手术。

CustomerRepo.GetThoseWhoHaventPaidTheirBill()

// or

GetCustomer(new HaventPaidBillSpecification())

// is better than

foreach (var customer in GetCustomer()) {
    /* logic leaking all over the floor */
}

“保存”类型方法也应该是存储库的一部分。

如果你有聚合根,这可以防止你有一个Repository爆炸,或者逻辑遍布:你没有4 x实体数据访问模式,只是你在聚合根上实际使用的模式。

那是我的$ .02。

===============>>#2 票数:5

DDD通常更喜欢使用Customer.Save提示的活动记录模式上的存储库模式。

Active Record模型的一个缺点是它几乎假设一个持久性模型,除非一些特别干扰的代码(在大多数语言中)。

存储库接口在域层中定义,但不知道您的数据是否存储在数据库中。 使用存储库模式,我可以创建一个InMemoryRepository,以便我可以单独测试域逻辑,并在应用程序中使用依赖注入,以使服务层实例化一个SqlRepository。

对于许多人来说,拥有一个特殊的存储库只是为了测试听起来很傻,但是如果你使用存储库模型,你可能会发现你并不真正需要一个特定应用程序的数据库。 有时一个简单的FileRepository会做到这一点。 在您知道自己需要之前向自己婚礼到数据库是有潜在限制的。 即使需要数据库,对InMemoryRepository运行测试也要快得多。

如果你没有太多的域逻辑,你可能不需要DDD。 ActiveRecord非常适合很多问题,特别是如果你主要拥有数据而且只是一点点逻辑。

===============>>#3 票数:4

让我们退一步吧。 Evans建议存储库返回聚合根而不仅仅是实体。 因此,假设您的客户是包含订单的聚合根,那么当您从其存储库中获取客户时,订单就随之而来。 您可以通过导航从客户到订单的关系来访问订单。

customer.Orders;

因此,为了回答您的问题,CRUD操作存在于聚合根存储库中。

CustomerRepository.Add(customer);
CustomerRepository.Get(customerID);
CustomerRepository.Save(customer);
CustomerRepository.Delete(customer);

===============>>#4 票数:3

我已经完成了你所讨论的两种方式,我现在首选的方法是持久的无知(或PONO - Plain Ole'.Net Object)方法,你的域类只担心是域类。 他们不知道如何坚持或即使他们坚持下去。 当然你有时候必须务实这一点,并允许诸如Id之类的东西(但即便如此我只使用具有Id的图层超级类型,所以我可以有一个点,其中像默认值这样的东西活着)

主要原因是我努力遵循单一责任原则。 通过遵循这一原则,我发现我的代码更易于测试和维护。 在需要时进行更改也更容易,因为我只有一件事要考虑。

需要注意的一件事是存储库可能遭受的方法膨胀。 GetOrderbyCustomer .. GetAllOrders .. GetOrders30DaysOld ..等。这个问题的一个很好的解决方案是查看查询对象模式。 然后你的存储库就可以接受一个查询对象来执行。

我也强烈建议调查像NHibernate这样的东西。 它包含许多使存储库如此有用的概念(Identity Map,Cache,Query对象......)

===============>>#5 票数:2

即使在DDD中,我也会将数据访问类和例程与实体分开。

原因是,

  1. 可测性得到改善
  2. 关注点分离和模块化设计
  3. 从长远来看,更加可维护,因为您添加了实体,例程

我不是专家,只是我的意见。

===============>>#6 票数:1

Nilsson应用DDD&P的烦人之处在于,他总是以“我不会在真实世界的应用程序中这样做但是......”开始,然后他的例子如下。 回到主题:我认为OrderRepository.GetOrdersByCustomer(客户)是要走的路,但也有关于ALT.Net邮件列表的讨论( http://tech.groups.yahoo.com/group/altdotnet/ )关于DDD。

  ask by Manu translate from so

未解决问题?本站智能推荐:

1回复

如何命名存储库用于数据访问的类?

我从事编程已经很多年了,最近我一直在尝试应用域驱动设计中的一些想法,但是我仍然很难为系统的某些部分确定好名字。 这是一个例子。 我有一个返回“计算机”对象的WCF Web服务。 该对象是包含子实体的聚合根。 子实体是从两个不同的数据库以及Active Directory中加载
11回复

在数据库而不是假存储库上运行测试是不好的做法吗?

我知道有什么好处,并且在使用更复杂的系统时会使用伪数据。 如果我正在开发一些简单的东西,并且可以轻松地在真实的数据库中设置我的环境并且所访问的数据是如此之小,以至于访问时间不是一个因素,并且我仅运行了一些测试,该怎么办? 创建伪数据是否仍然很重要,还是我可以忘记多余的编码而直接跳到真
3回复

DDD中的非业务逻辑数据库访问

只是从DDD开始。 我了解所有域实体及其逻辑应与存储库接口一起保留在域层中。 在我的应用程序中,我将一些数据存储在数据库中,这些数据用于在运行时构造用户界面(表示层)的各个部分。 在应用程序层或域层中,应将此类类型的poco类和存储库接口保留在何处。 我无法确定,因为这些对象将没有任何与
2回复

DDD中的数据访问层设计

对不起,我的英语很差。 好吧,我现在正在考虑DDD方法,听起来不错但是......有一个小问题。 DDD表示,域模型层与数据访问层(以及所有其他层)完全分离。 因此,当DAL将保存一些业务对象时,它将只能访问此对象的公共属性。 现在的问题是: 我们如何保证(通常)对象的一组
1回复

DDD中的参考数据

作为我上一个DDD旅程的上一个问题的后续,我在“发票”上下文中有一些关于项目代码的参考数据,这些参考数据在“配置”上下文中进行管理。 数据的一部分从配置镜像到发票(编号,名称),如果有人创建发票,我需要加载此信息以验证是否存在项目代码。 我应该在发票环境中将此物料代码参考数据建模为汇总根
2回复

数据访问层和DDD

我正在尝试学习域驱动设计的思想,并试图找出应该将数据库持久性代码放在哪里。 通过《 Vaughn Vernon实施域驱动的设计》一书,我了解到存储库或数据库操作(以及连接等)必须保留在Model项目(域模型上下文)本身中。 我的理解正确吗? 我指的是他的IdentityAccess
7回复

有没有PHP中的数据访问框架?

我是按行业划分的.net开发人员,但我希望扩展到PHP。 我真的很喜欢PHP可以做的事情。 但是,.net(例如LINQ)中的数据访问以及创建强类型数据集的难易程度使我有些受宠若惊。 是否有这种方法可以对PHP中的数据访问进行相同(或相似)的考虑? 我可能不知道的框架? 我目前正在
2回复

如何从PHP中的其他.php文件访问数据?

我有login.php和mainpage.php文件,我想从mainpage.php访问login.php的用户数据。 我应该使用require还是include ? 如何连接这些文件?
3回复

如何在Hibernate中限制数据库级别的用户访问

该应用程序 我需要实现一个将由不同用户使用的Web应用程序。 每个用户对各种表具有不同的权限,例如 用户A可以从表格Student查看字段'name'和'address' 用户B可以查看字段“名称”和“电话号码”,但不能查看表格Student “地址” 用户C可以查看
1回复

Silverlight数据访问

我正在开发一个silverlight报告工具,它根据客户数据绘制各种奇特的图形。 我现在遇到的问题是将我需要的所有数据从数据库获取到我的silverlight应用程序的好方法。 Sofar我有一个Web服务,将我的数据分成1000个组并将它们发回给我。 我需要超过3000条记录,这需要