Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.NET ORM需要虚拟的,并且可以';我不能处理密封的?_.net_Nhibernate_Entity Framework_Orm_Class Design - Fatal编程技术网

.NET ORM需要虚拟的,并且可以';我不能处理密封的?

.NET ORM需要虚拟的,并且可以';我不能处理密封的?,.net,nhibernate,entity-framework,orm,class-design,.net,Nhibernate,Entity Framework,Orm,Class Design,我刚刚开始使用.NETORMS,甚至还没有决定使用实体框架和NHibernate。但在这两种情况下,我都遇到了一个问题,因为他们似乎希望我以各种方式损害域模型的完整性,特别是在C#对象设计的更精细点上。这是关于这个问题的几个问题之一 有。我的域模型中的对象不准备承诺子类的行为,除非在非常特定的情况下我将它们标记为这样。换句话说,对于我的域对象上很少的方法来说,为未指定的新功能添加一个钩子是合适的 然而,NHibernate希望我把所有的都变成虚拟的,实体框架希望我把所有的实体引用都变成虚拟的。

我刚刚开始使用.NETORMS,甚至还没有决定使用实体框架和NHibernate。但在这两种情况下,我都遇到了一个问题,因为他们似乎希望我以各种方式损害域模型的完整性,特别是在C#对象设计的更精细点上。这是关于这个问题的几个问题之一


有。我的域模型中的对象不准备承诺子类的行为,除非在非常特定的情况下我将它们标记为这样。换句话说,对于我的域对象上很少的方法来说,为未指定的新功能添加一个钩子是合适的

然而,NHibernate希望我把所有的
都变成虚拟的
,实体框架希望我把所有的实体引用都变成虚拟的。我意识到他们为什么需要它(创建代理对象),我意识到它实际上是继承和
虚拟的合法使用-,他们实际上是连接到我的属性以添加新功能。但让我恼火的是,我必须用完全关于持久性的东西来注释我的域模型类,而不是表达它们与实现者和消费者的实际契约

作为一个较小的问题,我意识到我可能无能为力,通常用
密封的
注释我的类是很有表现力的。不过这有点不那么刺耳,因为为了持久性的目的而从我的域对象中省略注释似乎比添加注释更糟糕



令人沮丧的是,在读了几年《高效C#》或埃里克·利珀特(Eric Lippert)的博客(这些博客为如何设计富有表现力和防弹的C#对象提供了很好的建议)之类的书后,使用ORMs的需要让我把这些知识抛到了脑后。我希望在座的人能指出我的错误,无论是在我对他们的能力的理解上,还是在我对领域建模和ORMs角色的思考上。

不仅仅是.NET ORMs,同样的约束也适用于Java ORMs

尽管如此,在Java中,除非明确声明其他内容,否则所有内容都是虚拟的,因此满足ORM的需求与使用
密封的
时的情况非常相似:

为了持久性的目的而从我的域对象中省略注释似乎没有添加注释那么糟糕

归根结底,忽略持久性是一个值得追求的目标,但除非你也愿意忽略一些小细节,比如内存负载和性能,否则这不是一个100%可以实现的目标

如果不考虑内存负载和性能,请停止使用代理,并要求您的所有对象在水合后立即完全填充—NHibernate可以通过配置来完成此操作。副作用是,所有相关对象都将一次性加载,因此您最终会将大部分数据库加载到内存中。该应用程序需要大量内存,启动需要花费大量时间,但它可以正常工作


持久性是一个问题——虽然您可以将它的大部分隐藏在幕后,但总会有一些元素泄漏到应用程序的其他区域

如何轻轻地说。。。。对不起,我不能。忘掉它

我100%同意你的观点,但使用框架总是意味着妥协。不想妥协?你自己造吧。这就是一切

为了减少对抗性,您的问题有一个解决方案,那就是使用automapper之类的东西在泄漏的持久性子系统和应用程序的其余部分之间进行转换。基本上,你要保持你的领域模型干净整洁,按照你喜欢的方式设计,然后使用一个转换层在它和你讨厌的、丑陋的ORM之间映射

但是,这确实是一个很大的工作。而对于你放弃的少量纯度,你节省了很多努力

有一个原因是虚拟的不是 C#[链接到 采访安德斯·海尔斯伯格]

Hejlsberg实际上是在谈论框架API设计。他没有说任何关于业务线应用程序的事情。因此,他的规则在LOB应用程序中应用较少。因为您使用的是O/RM,所以您可能正在编写LOB应用程序

通常,注释我的 所有的课程都是密封的 原因[链接到Eric Lippert的博客]

您引用的是Eric Lippert的一篇文章,他在C#编译器团队的工作中撰写了这篇文章。一般原则实际上包含一条相反的指导方针:

在没有 这样做的理由很充分。[第6.3段]

换句话说,埃里克·利珀特所说的并不是一般的规则

就我个人而言,当我编写LOB应用程序时,我实际上会尽可能地密封我的类并编写非虚拟方法。但是,这与在以后的版本中引入突破性更改的更改无关,因为这几乎完全是一个框架设计问题

不,我这样做是因为它使我更容易对我的代码进行假设。换句话说:它使我的代码更易于维护

然而,当我需要这样做的时候,我绝对不会有任何问题,比如解封一个类或者虚拟化一个方法。我这样做的主要原因是允许我的代码是可测试的

显然,您也需要这种灵活性,因为您正在编写LOB应用程序,所以请实际一点,并记住:

他们更像是指导方针


无需在NHibernate中使所有内容都
虚拟化。
如果不使用“动态代理”,则不必将所有内容都虚拟化,并且可以将类密封起来

默认情况下,NHibernate使用动态代理。通过这样做,NHibernate创建了一个从您的类继承的类,这样它就可以确保
<class name="MyEntity" table="SomeTable" lazy="false">
</class>