我在尝试使用EF4应用DDD时遇到了几个问题(在ASP MVC2上下文中)。非常感谢您的推荐。
首先,我开始使用POCO,因为在许多情况下,对ObjectContext的依赖并不是很舒服。
去POCO解决了一些问题,但经验不是我习惯使用的NHibernate。
我想知道是否可以使用设计器,不仅可以生成实体,还可以生成值对象(ComplexType?)。如果我的意思是Value Object是一个没有任何设置属性的ctor类(需要进行T4修改?)。
我发现向贫血实体添加行为的唯一方法是创建扩展由edmx生成的部分类。我对这种方法不满意。
我不知道如何使用一个edmx创建多个存储库。现在我使用部分类来为每个聚合分组方法。事实上,每个组都是一个存储库。
最后一个问题是关于IQueryable。它应该暴露在存储库之外吗?如果我参考了这本书,那么存储库应该是一个执行单元,不应该暴露像IQueryable这样的东西。你觉得怎么样?
感谢您的帮助。
托马斯
答案 0 :(得分:4)
使用POCO很好,但请注意EntityObject
不需要ObjectContext
。
是的,复杂类型是值对象,是的,您可以在设计器中生成它们。选择实体的多个属性,右键单击,然后选择重构为复杂类型。
我强烈建议将业务方法放在自己的类型中,而不是实体上。如果你必须维护它们,“贫血”类型可能是一个问题,但是当它们被编码时,它们几乎不是维护问题。使业务逻辑与实体类型分离,可以使业务规则和数据模型独立发展。是的,如果你必须混淆这些问题,你必须使用部分课程,但我不认为将你的模型和你的规则分开是一件坏事。
我认为存储库应公开IQueryable
,但您可以提出域服务不应该这样做的好例子。人们经常尝试将他们的存储库构建到域服务中,但请记住,存储库的存在只是为了抽象出持久性。像安全这样的问题应该在域名服务中,你可以认为IQueryable
给消费者提供了太多的权力。
答案 1 :(得分:1)
我认为将IQueryable暴露在存储库之外是可以的,只是因为不这样做可能会产生不必要的限制。如果您只通过GetPeopleByBirthday
和GetPeopleByLastName
等方法公开数据,当有人按姓氏和生日搜索某人时会发生什么?您是否使用姓氏“Smith”吸引所有人并对您想要的生日进行线性搜索,或者您是否创建了新方法GetPeopleByBirthdayAndLastName
?那个必须实施QBE形式的可怜的倒霉的家伙呢?
当对域进行即席查询的唯一方法是生成SQL时,保证自己安全的唯一方法是提供检索和更改数据的特定方法。既然我们有LINQ,那么没有理由保持手铐。任何人都可以提交查询,您可以安全地执行它而无需担心。
当然,您可能会担心用户可能能够查看其他人的数据,但这很容易缓解,因为您可以限制您提供的数据。例如:
public IQueryable<Content> Content
{
get { return Content.Where(c => c.UserId == this.UserId); }
}
这将确保用户可以获得的唯一Content
行是那些拥有UserId
的行。
如果您担心的是数据库的负载,您可以执行以下操作:检查表扫描的查询表达式(访问没有Where
子句的表或Where
子句中没有索引列的表。当然,这是非平凡的,我不会推荐它。
答案 2 :(得分:0)
自从我提出这个问题并且有机会自己做这件事以来已经有一段时间了。
我不认为在DAL层之外公开IQueryable是一个好习惯。它带来了更多的问题。我在谈论大型MVC应用程序。首先,重构更难,许多开发人员从视图中使用IQueryable实例,并且在解决了IQueryable之后,已经处理了连接。性能问题,因为经常查询所有数据库以获取给定的结果集等等。
我宁愿从我的存储库中暴露出数字,相信我,它为我省去了许多麻烦。