如何在EntityFramework中更改自动生成的“Discriminator”列?

5

我正在处理一些与EF4.3单表继承相关的代码。

有一个名为User的实体和另一个名为Admin的实体。Admin继承自User。

User类

public class User
{
    public int Id {get;set;}
    public string Username {get;set;}
}

管理员类
public class Admin : User { }

EF生成了带有Discriminator列的数据库表。当添加一个Admin记录时,Discriminator =“Admin”,而User记录将具有Discriminator =“User”。
我的问题是,如果我想将用户变为管理员,如何更新Discriminator列?
我尝试从一种对象类型转换为另一种对象类型,并使用EF保存。但那不会更改Discriminator列。我该怎么改变它?
谢谢任何帮助。
1个回答

7

对象永远不能改变它们的类型。如果您打算更改用户的“管理员”设置(合理),则应使用属性/属性来进行更改,而不是类型名称。

例如,您可以在 User 对象和 Administrator 对象之间建立关联,而不是想要用 Administrator 子类型替换 User 对象。

我在一篇旧博客文章中写过这个想法

设计一个好的对象关系映射需要克服的心理障碍之一是倾向于以面向对象或关系为主,具体取决于个人的喜好。一个好的对象关系映射应当融合一个良好的对象模型和一个良好的关系模型。例如,假设您有一个 People 表格的数据库,并且有与之相关的 Employee 和 Customer 表格。一个人可能在这三个表格中都有记录。从纯粹的关系角度来看,您可以为员工和客户分别构建一个基于 People 表的数据库视图。在使用其中之一时,您可以暂时将个人视为“只是”员工或客户,即使您知道他们既是员工也是客户。因此,一个从这种角度出发的人可能会尝试使用 OO 映射,其中 Employee 和 Customer 都是 Person 的(直接)子类。但是,这与我们拥有的数据不符;由于单个人既有员工记录又有客户记录(并且由于没有一个 Person 实例可以同时属于 Employee 和 Customer 这两个具体的子类型),因此 Person 和 Employee 之间的 OO 关系需要是组合而不是继承,Person 和 Customer 同理。

直接回答你的问题,EF 没有办法更改这个列。当然,你可以用纯 SQL 来实现。但基于上述原因,我鼓励你改变这个设计。


对象永远不能改变它们的类型。但是它们可以转换为另一种类型。 - quakkels
1
强制类型转换并不改变类型。它要么创建一个新的实例(例如,使用显式转换),要么将引用视为更具体的类型。所有这些操作都不会改变判别值。 - Craig Stuntz
3
@quakkels:这可能需要对我正在工作的应用程序进行深入的重构。不幸的是,这通常发生在您错误地理解应用程序要求并使用错误设计的情况下。滥用继承是人们在应用程序中可以做的最糟糕的事情之一,因为在开发的后期修复这种设计错误通常是很昂贵的。 - Ladislav Mrnka
我脑海中首先想到的是用一个新的管理员替换现有用户,并保留相同的数据:User user = GetUser(); Admin admin = Admin.FromUser(user); dbContext.Users.Remove(user); dbContext.Admins.Add(admin);。这样做有什么不好的原因吗? - 41686d6564 stands w. Palestine
@AhmedAbdelhameed 如果你的系统从一开始就考虑到“人员”记录随时间变化的概念,那么这并不是一个坏主意。但如果你在数据库中有1000个外键与该人员相关联,那么仅仅替换记录可能会很具有挑战性。因此,这取决于你的设计。我可能会将你的示例建模为一个带有角色历史记录的人员。 - Craig Stuntz
显示剩余2条评论

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