使用实体框架进行向下转型
我有一个项目,在 EF 中定义了一个 Employer
作为 User
的派生类。在我的过程中,我创建了一个用户,但不知道它最终是否会成为雇主(或其他类型的用户),稍后我需要将其转换。起初我尝试过(智能感知表明存在显式转换):
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<Employer>()
.Single();
... GetUser()返回一个 User
类型的对象,它不提供 .Cast<>
所以我使用直接查询来到达那里......但我仍然得到动态的转换代理对象异常。
所以我的问题是:当对象通过 EF 持久化时,我该如何向下转型?
I have a project where I've defined in EF an Employer
as a derived class of User
. In my process I create a user without knowing whether it will eventually be an employer (or other kinds of users) and later I need to convert it. At first I tried (Intellisense indicated an explicit conversion exists):
Employer e = (Employer) GetUser();
but at runtime I got:
Unable to cast object of type 'System.Data.Entity.DynamicProxies.User_7B...0D' to type 'Employer'.
so I tried to write a converter:
public partial class User
{
public static explicit operator Employer(User u)
{
but I get the error:
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
fine. I then overloaded the constructor for Employer
like this:
public partial class Employer
{
public Employer(User u)
{
this.Id = u.Id;
this.Claims = u.Claims;
// etc.
}
}
and figured I could then just do:
Employer e = new Employer(GetUser());
but when I run it I get the error:
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
as a last resort I tried writing this:
Employer e = Auth.Claims("id")
.Where(x => x.Value == Auth.NameIdentifier())
.Select(x => x.User)
.Cast<Employer>()
.Single();
... GetUser() returns an object of type User
which does not offer the .Cast<>
so I used a direct query to get there... but I still get the casting of dynamic proxy objects exception.
so my question is: how can I downcast when the object has persistence through EF?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是不可能的。您必须始终使用最终类型。一旦您将其创建为
User
,EF 将永远不会允许您将其更改为派生实体类型。顺便提一句。使用面向对象的方法也是不可能的。您不能将父类的实例强制转换为派生类的实例(除非它确实是派生类的实例) - 它将在运行时抛出异常。重现该问题的非常简单的示例:
唯一的方法是重写转换运算符,它将在内部创建派生类的新实例,并将所有字段从旧的父实例复制到新的派生类。
实体框架需要完全相同的方法。如果您从
User
实体开始,现在想要将其提升为Employer
实体,则必须删除旧用户并创建新的Employer
。It is not possible. You must always use final type. Once you create it as a
User
, EF will never allow you changing it to a derived entity type.Btw. it is also not possible with object oriented approach as well. You cannot cast instance of parent class to the instance of derived class (unless it really is instance of derived class) - it will throw exception at runtime. Very simple example to reproduce the issue:
The only way to do that is overriding conversion operator which will internally create a new instance of derived class and copy all fields from the old parent instance to that new derived one.
Exactly the same approach is needed with entity framework. If you started with
User
entity and now you want to promote it toEmployer
entity you must delete old user and create newEmployer
.假设您的雇主实体仅具有可为空的属性,则可以转到数据库中的表并将鉴别器从用户更改为雇主。所有关系都将保留。而且也可以做相反的事情。
Supose that your Employer entity has only nullable properties then it is possible to go to the table at the database and change the Discriminator from User to Employer. All relationships will be kept. And also it is possible to do the opposite.