我目前正在努力重写一个应用程序,以使用完全从Domain层抽象数据库的Data Mappers.但是,我现在想知道哪个是处理Domain对象之间关系的更好方法:
直接在域对象中从相关数据映射器调用必要的find()方法
将关系逻辑写入本机数据映射器(这是示例在PoEAA中执行的操作),然后在域对象中调用本机数据映射器函数.
在我看来,为了保留'Fat Model,Skinny Controller'的口头禅,域对象必须知道数据映射器(无论是他们自己还是他们可以访问系统中的其他映射器) .此外,似乎选项2不必要地使数据访问层复杂化,因为它跨多个数据映射器创建表访问逻辑,而不是将其限制在单个数据映射器中.
那么,让域对象知道相关数据映射器并直接从域对象调用数据映射器函数是不正确的吗?
更新:这是我可以设想的唯一两个解决域对象之间关系问题的解决方案.任何显示更好方法的例子都是受欢迎的.
是.问问自己为什么域名对象会知道这样的事情?甚至不是为什么,但如何?你要将DAL注入你的Domain对象吗?
该域名应遵循SRP,只需将其他所有内容都存在.当您遍历您的域时,您应该不知道这些属性是通过延迟加载填充还是从实例化中保存.
我编写了一个域模型,其中包含DAL对象,这是一个维护的噩梦.然后我学习了NHibernate,我的域名由POCO和我想要封装的各自的业务逻辑组成.
[编辑]
这是更多信息.如果我试图解释它,我只会让自己难堪.我只能说作为用户的实现.这是一篇关于域模型管理的精彩文章.你感兴趣的是拦截器和mixin的实现.
使用这些工具,您可以编写员工类,如下所示:
public class Employee { public Employee() { Skills = new List(); } public string Name { get; set; } public IList Skills { get; private set; } public void AddSkill(Skill skill) { // Perform Domain specific validation here... Skills.Add(skill); } }
如您所见,我的数据访问需求不会强加于我的域设计.
我担心你会略微误解Repository模式的意图.
存储库的行为类似于特定域对象的内存中集合,通常是聚合根:
interface EmployeeRepository { ListretrieveBy(Criteria someCriteria); void store(Employee someEmployee); int countOf(Criteria someCriteria); // convenience methods Employee retrieveById(String id); Employee retrieveBySSN(String ssn); }
此代码的客户端不知道集合是否在内存中,就像您在单元测试中所做的那样,或者在某些情况下与ORM映射器通信,或者在其他情况下调用存储过程,或者为某些域对象维护缓存.
这仍然无法解答您的问题.实际上,您可能有域对象具有委托给正确的存储库的save()和load()方法.我不认为这是正确的方法,因为持久性几乎从不是业务领域的一部分,它为您的域对象提供了多个改变的理由.
查看此相关问题以获得更多漫游.
回应一些关于这个答案的评论:
一个有效的批评.但是,我仍然对如何在现有域对象的上下文中获取单个域对象或相关域对象的集合感到困惑. - gabriel1836
让我们说一个员工有很多技能.我认为Employee Repository调用Skill Repository是这样的:
// assume EmployeeRepository talks to a DB via sprocs public Employee retrieveById(String id) { ResultSet employeeResultSet = this.database.callSproc("PROC_GetEmployeeById", new Object[] { id }); Listskills = new SkillRepository().retrieveBy(new EqualsCriteria("EmployeeId", id)); Employee reconstructed = new EmployeeFactory().createNew(). fromResultSet(employeeResultSet). withSkills(skills). build(); return reconstructed; }
另一个路径是调用Skill Repository,让Employee Repository调用(在本例中)存储过程来加载技能的结果集,然后委托Skill Factory获取Skills列表.
我无法调用存储库以及它是否发出对数据映射器的调用或者将对象加载到内存中是关注的问题,不是吗? - gabriel1836
非常正确.我通常以这种方式在单元测试中模拟整个数据层.