DDD,存储库,数据映射器等周围似乎发生了很多“噪音”...而且很少有“真实世界”的实现代码向我这样的新手展示什么是“好”,什么是“坏”。
我刚刚读完了这本书Architecting Applications for the Enterprise,这让人大开眼界。我目前在工作中使用Active Record模式,并且一直在努力将其更改为使用Domain Model。我在本书中使用了很多架构示例,以及与本书相关的Northwind Starter Kit代码下载。
一切都很顺利,但现在我已经遇到了我的第一个“真实世界”数据映射器问题...而不是我的映射器只负责获取一个Entity对象并将其持久化到数据库,我现在拥有一个具有IList<>的Entity对象还需要映射的集合。主要的Entity对象是Expert,这是代码:
public class Expert
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual IList<Case> Cases { get; protected set; }
}
以下是Expert对象集合的实现:
public class Case
{
public int ID { get; set; }
public string Name { get; set; }
}
不能比那简单得多。
现在,我为每个实体项都有一个DataMapper,但我的问题是,当我在ExpertDataMapper代码中映射Case集合时,什么被认为是“正确”的方法呢?
在本书中,实际的SQL代码嵌入在ExpertDataMapper中,该代码调用ADO.NET代码,该代码获取IList集合中的所有Case项,并为每个项调用该代码一次。这是一些伪代码:
public virtual void Create(Expert expert)
{
// Insert expert in the Expert table
SqlHelper.ExecuteNonQuery(ProviderHelper.ConnectionString, CommandType.Text,
"SQL TO INSERT EXPERT", this.BuildParamsFromEntity(expert));
// Insert individual Case items in the Case table
foreach (Case c in expert.Cases)
{
SqlHelper.ExecuteNonQuery(ProviderHelper.ConnectionString, CommandType.Text,
"SQL TO INSERT CASE", this.BuildParamsFromEntity(order));
}
}
因此,有两件事情出现在我面前:
我认为ExpertDatMapper应该将Case插入到CaseDataMapper中的任务...但我不知道一个DataMapper是否“正确”或“错误”来实例化另一个。这被认为是DataMappers的常见问题吗?我没有找到关于这个问题的指导,我认为这是很常见的。
因此,当涉及到DataMappers时,我还没有在实体对象的DataMaper上看到任何具有简单集合关联的简单创建,更新等的具体实现。我正在阅读的这本书没有代码可以支持它(那里的代码看起来很可疑)。
我已阅读并拥有Martin Fowler的EA EA书籍,所以请不要告诉我看那里。我也知道可以使用的ORM工具,所以我不需要自己实现DAL。我玩过EF 4.0,我喜欢它。但是对于这个项目,我没有选择使用ORM工具。
大多数书籍/示例似乎停留在相同的基本前提下,只要我的Entity对象与通过DataMapper持久保存的表之间存在一对一的关联,世界就是玫瑰色的使用域模型方法......
如果我的所有实体都是一对一的,我不妨使用Active Record并完成它。
任何指导,建议,见解?对不起,这是一个很长的帖子,但我在这里看到了其他类似问题的帖子,没有真正具体的答案或如何处理这里提出的问题的建议。
答案 0 :(得分:4)
关于第一点,从“SOLID”的角度来看,你是对的。而不是处理持久性本身,实现ExpertDataMapper使用的CaseDataMapper将更易于维护和更少冗余。这可能不是出于几个原因,主要与简单性有关。如果您有一个应在同一事务中工作的单独类,则必须传递该事务。这本身并不可怕,但它引入了更多关于如何使实现架构独立的问题。如果您只是通过事务处理,那么您将与vanilla ADO.NET结合,并且无法在以后升级到像MSEF,NHibernate,Linq2SQL等ORM。因此,您需要一个UnitOfWork模式,它允许您隐藏实际事务或会话或DataContext或存储库中的任何内容。到目前为止,这个相对简单的代码片段现在是两个完整的类定义,有很多东西。
为了避免所有这些,为了说明一个Expert,他们只是将代码保存在Expert中。这基本上假设Case总是被引用为Expert的子代,因此将功能切换为可以重用的东西是不值得的。吻。这个假设可能是真的;如果没有,那么将它作为练习留给读者将该逻辑重构为帮助者。
关于第二点,你也是对的,而且真的没有办法解决它。从SQL Server无法了解的数据创建的每一行必须一次插入一行。你可能会以某种方式设置批量插入,但我可以保证比你的价值更麻烦,直到你进入成千上万的记录。您使用的任何ORM都会产生相同的SQL。
在不使用ORM的情况下:如果您没有使用预制ORM,那么如果您不想使用预制ORM,那么如果您希望它符合SOLID等设计方法,您将最终自行滚动。
答案 1 :(得分:3)
这实际上取决于个人偏好和意见。一些开发人员会说你所展示的代码没有任何问题。其他人会说每个班级只对自己的州和财产负责。其他人也会说其他的东西。你应该使用适合自己的东西,即:你觉得自己感觉舒适。就个人而言,我更喜欢使用EF Code First,它允许我轻松创建我的模型类和我的数据库上下文类。然后我简单地使用存储库模式和负责提交事务的UnitOfWork类来抽象。此外,依赖注入模式是松散您的类的好方法。我的类紧密耦合存在重大问题,如果不使用IoC容器我无法解决。
This article是迄今为止我见过的最佳资源。作者在创建一个完全可行且最重要的可扩展框架方面做得非常出色。
祝你好运:)