使用entity framework进行向下转型

我有一个项目,我在EF中将Employer定义为User的派生类。 在我的过程中,我创建一个用户,而不知道它最终是否会成为雇主(或其他类型的用户),之后我需要转换它。 起初我尝试过(Intellisense表示存在显式转换):

 Employer e = (Employer) GetUser(); 

但在运行时我得到了:

 Unable to cast object of type 'System.Data.Entity.DynamicProxies.User_7B...0D' to type 'Employer'. 

所以我试着写一个转换器:

 public partial class User { public static explicit operator Employer(User u) { 

但我得到错误:

 Error 21 'User.explicit operator Employer(User)': user-defined conversions to or from a derived class are not allowed C:\Users\..\Documents\Visual Studio 2010\Projects\..\Website\Models\EF.Custom.cs 

精细。 然后我重载了Employer的构造函数,如下所示:

 public partial class Employer { public Employer(User u) { this.Id = u.Id; this.Claims = u.Claims; // etc. } } 

并认为我可以这样做:

 Employer e = new Employer(GetUser()); 

但是当我运行它时,我得到错误:

 System.InvalidOperationException was unhandled by user code Message=Conflicting changes to the role 'User' of the relationship 'EF.ClaimUser' have been detected. Source=System.Data.Entity StackTrace: [...] at Controllers.AuthController.Register(String Company, String GivenName, String Surname, String Title, String Department) in C:\Users\..\Documents\ Visual Studio 2010\Projects\..\Website\Controllers\AuthController.cs:line 

作为最后的手段我尝试写这个:

  Employer e = Auth.Claims("id") .Where(x => x.Value == Auth.NameIdentifier()) .Select(x => x.User) .Cast() .Single(); 

… GetUser()返回一个User类型的对象,该对象不提供.Cast所以我使用直接查询到达那里……但我仍然得到了动态代理对象exception的转换。

所以我的问题是:当对象通过EF持久化时,我怎么能垂头丧气?

这不可能。 您必须始终使用最终类型。 一旦您以User身份创建它,EF将永远不允许您将其更改为派生实体类型。

顺便说一句。 使用面向对象的方法也是不可能的。 您不能将父类的实例强制转换为派生类的实例(除非它确实是派生类的实例) – 它将在运行时抛出exception。 重现问题的非常简单的示例:

 class X { } class Y : X { } class Program { static void Main(string[] args) { X x1 = new Y(); Y y1 = (Y)x1; // Works X x2 = new X(); Y y2 = (Y)x2; // InvalidCastException } } 

唯一的方法是覆盖转换运算符,它将在内部创建派生类的新实例,并将旧父实例中的所有字段复制到新派生的实例。

entity framework需要完全相同的方法。 如果您从User实体开始,现在要将其提升为Employer实体,则必须删除旧用户并创建新的Employer

假设您的Employer实体只有可以为空的属性,那么就可以转到数据库中的表并将Discriminator从User更改为Employer。 所有关系都将保留。 而且也可以做相反的事情。