更改继承层次结构中的(Entity Framework)实体类型

9

我有一个继承层次结构,其中有一个基本的Employee实体和一些特定员工类型的子类实体。我需要能够将基本的Employee实体转换为更具体的实体(例如TemporaryEmployee),并从更具体的类型转回到基本类型(例如,如果员工不再是“临时”的,则希望该实例仅作为Employee持久化。

在数据库中,这只是在特定子类的表中添加或删除行的问题。(我正在使用按类分表)但我没有看到如何使用EF调用来完成此操作。

2个回答

8
OOP的原则之一是实例不能改变其类型。想想:你能用普通的.NET对象做到这一点吗?当然不行。你也不能通过使用EF将它们持久化来规避这个坚定不移的规则。
将一行添加到数据库中也不会改变实例的类型;它只是欺骗了EF关于你保存了什么的信息。在关系域中,你正在添加一个关系,而不是更改对象的类,因为关系域不知道对象。
因此,使用EF不会改变.NET实例不能改变其类型的规则。
那么,当您需要这样做时该怎么办呢?好吧,考虑一下这在您的问题域中是如何工作的。员工是一个人。他们的就业状况与人有关,但他们的状态并不是人。
使用组合而不是继承。我可能会将其建模为人员,带有就业实例的集合。随着一个人的就业情况的变化,您可以为旧记录分配停止/终止日期,并为新工作添加新记录。

今天早上我偶然看到了这篇博客文章,这可能会给你更多的思考启示。

编辑补充 如果你通过实现数据库存储过程来解决这个问题,请确保在执行时没有人正在使用系统。因为在.NET对象空间中,这是完全非法的,Entity Framework认为这是不可能发生的。如果你绕过Entity Framework并这样做,并且用户恰好在此时有一个活动的ObjectContext,则该ObjectContext将与数据库不同步,而Entity Framework中的正常乐观并发保护无法检测到这种情况。你不会破坏数据,但具有活动ObjectContext的用户可能会看到一些极其奇怪的错误。


1
好的注释。在这里继承似乎更自然,因为它允许我定义更具体类型之间的关系。 是的,你链接的博客文章很有趣 - 将实体更改为基本类型是一种删除的形式 - 也许我根本不应该这样做... - Craig Fisher
关于你所添加的编辑:EF 不能假设它是唯一更新数据库的进程。实际上,在大多数情况下,它并不是 - 在同一数据库上可能至少有多个 ObjectContext 实例在运行(例如,在 Web 应用程序的每个用户中就会有一个)。 - Craig Fisher
我没有说EF认为它是唯一更新数据库的进程,因为那是错误的。我说当某些外部进程“损坏”数据库时,EF会返回奇怪的错误消息。而EF认为更改实例的类型是一种损坏,原因非常充分。只有在(1)存在一个活动对象上下文并且对象在内存中,然后(2)某个其他用户“更改了类型”,然后(3)原始上下文对该对象进行操作时,这才是一个问题。EF将检测到此问题并返回高度技术性的错误。就像我说的,这样做并不是多用户安全的。 - Craig Stuntz
在EF映射的表中,你不能使用FK作为PK这种说法是不正确的。我们在我们的模型中经常这样做。事实上,这是我发现可靠地使GUI设计师正确获取关系基数的唯一方法。如果不了解更多信息,我无法确定问题出在哪里。 - Craig Stuntz
GUI 设计师在3.5版本中确实完全不理解分割表映射。 - Craig Stuntz
显示剩余2条评论

4

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

然而,我完全同意Craig的观点。在经典编程书籍《设计模式》(Addison-Wesley Professional)中,作者讨论了继承与组合,并得出结论应该“优先选择组合而非继承”。


是的,目前我使用存储过程来实现这个功能。这也是微软的建议: “您不能直接在Entity Framework中完成此操作。您最好的选择是编写存储过程来进行这些转换。” http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/860d7913-7baa-43e9-a2a7-83b25ad9c558/ - Craig Fisher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接