我挖掘了很多关于 DDD方法(无处不在的语言,聚合,存储库等)的东西,我认为,与我经常阅读的内容相反,实体应该有行为而不是不可知论者。我看到的所有示例都倾向于使用虚拟自动属性和空构造函数(受保护或最差,公共)呈现实体,就是这样。我认为这种对象更像是DTO然后是实体。
我正在使用其特定的API 创建框架,我不想绑定到ORM 。所以我首先构建了域(不考虑持久性),现在我想使用NHibernate作为持久性工具,所以我在当前的解决方案中添加了一个新项目,以帮助确保我的模型不会被改变以支持NHibernate。该项目应该是我域内的抽象存储库的实现。现在出现了困难。
因为这是我第一次使用NHibernate (我也尝试使用Fluent Nhibernate,但似乎更有限制)我想知道:
请记住,我正在构建一个框架,因此Open/Closed Principle对我来说非常重要。
P.S。:对不起,如果我的英语不好,我来自蒙特利尔,我说法语。
编辑1:以下是我对NHibernate的一个问题 - How to map Type with Nhibernate (and Fluent NHibernate)
答案 0 :(得分:9)
virtual
。这包括所有引用属性和所有集合属性。这是因为NHibernate必须能够生成派生映射类并覆盖映射属性的代理类。IList<T>
而不是List<T>
。这是因为.NET Framework中的集合类型往往是密封的,并且NHibernate必须能够用它自己的集合类型实例替换集合类型的默认实例,并且NHibernate有自己的集合类型的内部实现Iesi.Collections.Generic.ISet<T>
到System.Collections.Generic.IList<T>
,除非您确定所需内容实际上是列表而不是 set 。这需要熟悉 list 和 set 的理论定义以及您的域模型所需的内容。当您知道元素必须按特定顺序排列时,请使用列表。另请注意,交换对象关系映射框架通常并不容易,并且在很多情况下,当您有超出简单域模型的任何内容时,这是不可能的。
答案 1 :(得分:4)
对你的问题的简短回答是,这是不可能的,但如果不需要延迟加载,则所需的修改是微不足道的。
无论如何,您都会将默认构造函数添加到尚未拥有它们的类中。如果您愿意放弃延迟加载,那些默认构造函数可以是私有的,并且您不必对域模型进行任何其他更改即可使用NHibernate。
这非常接近持久性的无知。
话虽如此,如果你想要延迟加载,你需要进行一些更改(在这个问题的其他答案中概述),以便NHibernate可以创建聚合实体的代理。我个人仍然试图决定延迟加载是否是DDD的支持技术,或者是否是过早的优化需要对我的POCO进行太多的侵入式更改。我倾向于前者,但我真的希望NHibernate可以配置为使用特定的构造函数。
你也可以看看Davy Brion的博客(我特别喜欢Implementing A Value Object With NHibernate),如果你对领域驱动设计和避免贫血领域模型感兴趣,这真的很有启发性。
答案 2 :(得分:4)
根据我的经验,NHibernate对域的唯一要求是虚拟属性和方法以及默认的无参数构造函数,如Jeff所述,如果需要,可以将其标记为私有或受保护。而已。 NHibernate是我的首选OR / M,我发现整个NHibernate堆栈(NHibernate,NHibernate Validator,Fluent NHibernate,LINQ to NHibernate)是持久存储POCO域的最引人注目的框架。
使用NHibernate可以做的一些事情:
您必须做出的唯一妥协是在您的域中使用NHV属性。这对我来说不是一个交易破坏者,因为NHV是一个独立的框架,如果你选择使用NHibernate,它会增加额外的功能。
我已经使用NH构建了一些应用程序,每个应用程序都有一个持久性无知域,所有持久性问题都分成了自己的程序集。这意味着您的域的一个程序集,另一个用于流畅的映射,会话管理和验证集成。它非常干净整洁,能很好地完成工作。
顺便说一句:你的英语非常好,我希望我的法语达到标准杆;-)。
答案 3 :(得分:0)
只是为了把我的两个位置,我曾经用同样的东西挣扎但是我克服了这个:
让我们在我的实验网站上为投票实体提供upvote和downvote: http://chucknorrisfacts.co.uk/(NHibernate + MySQL和Mono)
public class Vote : Entity
{
private User _user;
private Fact _fact;
// true: upvote, false: downvote
private bool _isupvoted;
// for nHibernate
protected Vote() { }
public Vote(User user, Fact fact, bool is_upvoted)
{
Validator.NotNull(user, "user is required.");
Validator.NotNull(fact, "fact is required.");
_fact= fact;
_user = user;
_isupvoted = is_upvoted;
}
public User User
{
get { return _user; }
}
public Fact Fact
{
get { return _fact; }
}
public bool Isupvoted
{
get { return _isupvoted; }
}
}
这个类继承自 Entity ,其中我们坚持Nhibernate所需的所有最小值。
public abstract class Entity
{
protected int _id;
public virtual int Id { get {return _id;} }
}
和Fluent映射您显示私有财产的位置。
public class VoteMap : ClassMap<Vote>
{
public VoteMap()
{
DynamicUpdate();
Table("vote");
Id(x => x.Id).Column("id");
Map(Reveal.Member<Vote>("_isupvoted")).Column("vote_up_down");
References(x => x.Fact).Column("fact_id").Not.Nullable();
References(x => x.User).Column("user_id").Not.Nullable();
}
}
您可以将受保护的默认构造函数放在Entity类中,并将nHibernate配置为使用它,但我还没有查看它。