2009-09-01 46 views
7

我有一个基础Employee实体和特定雇员类型的一些派生实体的继承层次结构。我需要能够将基础Employee实体转换为更具体的实体(例如TemporaryEmployee),并从更具体的类型转换回基本类型(例如,如果员工不再是“临时”的,那么我希望该实例只是持久化为Employee 在数据库中,这只是从表中为特定子类添加或删除一行的问题(我使用的是每个类的表)。但是我没有看到如何使用EF调用来完成此操作更改属于继承层次结构一部分的(实体框架)实体的类型

回答

4

从技术上讲,您可以通过使用存储过程来实现它。 TPT不支持它。

但是,我完全同意克雷格。在经典的编程书籍设计模式(Addison-Wesley Professional)中,作者讨论了继承与构图,并得出结论认为应该“赞成构图而不是继承”。

+0

是的,现在我已经使用存储过程实现了这一点。 这也是MSFT的建议: “你不能直接在实体框架中这样做,你最好的选择是编写存储过程来完成这些转换” http://social.msdn.microsoft.com/Forums/ EN-US/adodotnetentityframework /线程/ 860d7913-7baa-43e9-a2a7-83b25ad9c558 / – 2009-09-01 20:55:45

7

OOP的原理之一是实例不能改变它们的类型。想一下:你可以用普通的.NET对象来做这件事吗?当然不是。坚持他们与EF,要么

向数据库添加一行不会改变实例的typ e,要么;它只是EF的谎言,关于你保存的东西。在关系域中,您添加了一个关系,而不是更改对象的类,因为关系域不知道对象。

因此,长期和短的是,使用EF不会改变.NET规则,即实例不能改变它们的类型。

当你需要这样做时,你应该怎么做?那么,想想这是如何工作在你的问题领域。员工是一个人。他们的就业状况与该人有关,但他们的身份实际上并不是人。

使用组合而不是继承。我可能会将此模型设置为Person,并带有一系列Employment实例。当一个人的就业情况发生变化时,您可以将停止/终止日期分配给旧记录,并为新作业添加新记录。

我碰巧读了this blog post今天早上,这可能是进一步的思考。

编辑为添加如果您通过实施DB存储过程来解决此问题,请确保没有人在执行时实际使用系统。因为这在.NET对象空间中是完全非法的,所以实体框架认为它不可能发生。如果您绕开实体框架并执行此操作,并且用户碰巧有一个活动的ObjectContext,则此实体框架中的正常乐观并发保护未检测到此ObjectContext与数据库不同步。您不会损坏数据,但具有活动ObjectContext的用户可能会看到一些令人难以置信的奇怪错误。

+1

好评。继承在这里似乎更自然,因为它允许我定义更具体的类型之间的关系。 是的,你也链接到有趣的博客文章 - 将实体更改为基本类型是一种删除形式 - 也许我不应该这样做...... – 2009-09-01 20:53:27

+0

关于您添加的编辑:EF不会并且不能假设它是更新数据库的唯一过程。事实上,在大多数情况下,它不是 - 您可能至少有多个ObjectContext实例针对同一个数据库(例如,在Web应用程序中每个用户一个)运行。 – 2009-09-02 15:56:58

+0

我没有说EF假定它是更新数据库的唯一过程,因为那是错误的。我说,当某些外部进程“损坏”数据库时,它会返回奇怪的错误消息。考虑到很多原因,EF考虑将实例的类型改为腐败。这只是一个问题,如果(1)与内存中的对象存在活动对象上下文,则(2)其他用户“改变类型”,然后(3)原始上下文对对象执行某些操作。 EF将检测到问题并返回高度技术性错误。就像我说的那样,这样做并不是多用户安全的。 – 2009-09-02 16:23:38