3

Employerの派生クラスとしてEF で定義したプロジェクトがあり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<Employer>()
            .Single();

User... GetUser() は提供しないタイプのオブジェクトを返す.Cast<>ので、そこに到達するために直接クエリを使用しました...しかし、それでも動的プロキシ オブジェクトのキャスト例外が発生します。

だから私の質問は:オブジェクトがEFを介して永続性を持っている場合、どうすればダウンキャストできますか?

4

2 に答える 2

7

それは不可能。常に最終型を使用する必要があります。として作成するとUser、EF では派生エンティティ型に変更することはできません。

ところで。オブジェクト指向のアプローチでも不可能です。親クラスのインスタンスを派生クラスのインスタンスにキャストすることはできません (実際に派生クラスのインスタンスでない限り)。実行時に例外がスローされます。問題を再現するための非常に簡単な例:

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
    }
}

これを行う唯一の方法は、派生クラスの新しいインスタンスを内部的に作成し、すべてのフィールドを古い親インスタンスからその新しい派生インスタンスにコピーする変換演算子をオーバーライドすることです。

エンティティ フレームワークでもまったく同じアプローチが必要です。エンティティから始めてUserエンティティに昇格させたいEmployer場合は、古いユーザーを削除して新しいを作成する必要がありますEmployer

于 2011-09-01T07:39:32.453 に答える