用Fluent NHibernate进行映射时编程接口
我已经被提交并已经开始学习流利NHibernate(没有以前的NHibernate经验)。 在我的项目中,我对接口进行了编程以减少耦合等。这意味着几乎“一切”是指接口而不是具体类型(即消息而不是消息)。 这背后的想法是通过能够嘲讽依赖性来帮助使其更具可测性。
然而,(流利)NHibernate不喜欢它,当我试图映射到接口,而不是具体的类。 这个问题很简单 - 根据Fluent Wiki,例如定义我的类的ID字段是明智的
int Id { get; private set; }
得到一个典型的自动生成的主键。 但是,这只适用于具体的类 - 我不能在接口上指定访问级别,而同一行必须位于此级别
int Id { get; set; }
我想这会否定让setter在具体类中是私有的(这个想法是只有NHibernate应该设置由DB分配的ID)。
就目前而言,我想我只是让公开发布者,并尽量避免写入它的诱惑。但是,有没有人知道什么是“正确”,最佳实践方式来创建适当的主键只有NHibernate可以写入的字段,而只能编程到接口?
更新
根据我在mookid和James Gregory的下面两个答案后所了解的情况,我可能会走上错误的轨道 - 我不应该有像现在这样拥有每个实体的接口的理由。 这一切都很好。 我想我的问题变成了 - 是否没有理由针对任何实体的接口编程100%? 如果甚至有一种情况可以证明这是合理的,那么使用(Fluent)NHibernate可以做到这一点吗?
我问,因为我不知道,不要批评。 感谢您的回应。 :)
更新:通过fluent-nhibernate提供的流畅接口不支持使用union-subclass。 您必须使用常规的HBM映射文件并添加它。
我也尝试用流利的NHibernate来做这件事。 我不认为它应该是一个映射接口的问题。 你想要使用继承策略,特别是每个具体类的策略。
本质上,你为基类(在这里是你的接口)创建一个映射定义,并指定NHibernate应该如何使用union-subclass处理实现者。
所以,例如,这应该允许你进行多态关联:
<class name="IAccountManager"
abstract="true"
table="IAccountManager">
<id name="Id">
<generator class="hilo"/>
</id>
<union-subclass
table="DefaultAccountManager"
name="DefaultAccountManager">
<property name="FirstName"/>
</union-subclass>
<union-subclass
table="AnotherAccountManagerImplementation"
name="AnotherAccountManagerImplementation">
<property name="FirstName"/>
</union-subclass>
...
</class>
请注意,所有具体实施者的Id是如何相同的。 NHibernate需要这个。 另外,IAccountManager表实际上不存在。
你也可以尝试和利用NHibernate的Implicit Polymorphism(隐式多态)(在每个具体类的策略下面记录) - 但它有很多限制。
我意识到这是一个转移,而不是你的问题的答案(尽管我认为mookid已经涵盖了这一点)。
您应该真正评估您的域实体上的接口是否实际上提供了任何有价值的东西; 很难找到真正需要这样做的情况。
例如:如何依赖IMessage
比依赖Message
更少耦合,当它们(几乎)毫无疑问地共享相同的签名时? 你不应该嘲笑一个实体,因为它很少有足够的行为来要求被嘲笑。
您可以调整您的界面以仅包含一个吸气剂:
public interface ISomeEntity
{
int Id { get; }
}
你的具体类仍然可以实现一个setter,并且由于你正在编程你的接口,所以你将永远不会无意中调用setter。
如果你想禁止设置id,即使你持有一个具体实例的引用,你也可以避免实现一个setter,然后让NHibernate访问该字段而不是属性 - 这是正确的,NHibernate可以使用一些漂亮的反射技巧来直接设置你的id字段而不是调用属性。 那么你可以像这样映射id:
Id(e => e.Id).Access.AsCamelCaseField();
在这种情况下,您的Id
属性必须由相应的id
字段支持。 有更多的命名约定,例如,如果你喜欢下划线作为私人字段前缀。
上一篇: Programming to interfaces while mapping with Fluent NHibernate