プロキシの操作

POCO エンティティ型のインスタンスを作成する場合、Entity Framework では、通常、エンティティのプロキシとして機能する動的に生成される派生型のインスタンスが作成されます。 このプロキシは、プロパティがアクセスされたときにアクションを自動的に実行するフックを挿入するために、エンティティの一部の仮想プロパティをオーバーライドします。 たとえば、このメカニズムは、リレーションシップの遅延読み込みをサポートするために使用されます。 このトピックで紹介するテクニックは、Code First および EF Designer で作成されたモデルに等しく使用できます。

プロキシ作成を無効にする

Entity Framework によってプロキシ インスタンスが作成されないようにすると便利な場合があります。 たとえば、プロキシ インスタンスをシリアル化するよりも、非プロキシ インスタンスをシリアル化する方がかなり簡単です。 プロキシの作成は、ProxyCreationEnabled フラグをオフにすることによって無効にできます。 それができる場所の 1 つは、コンテキストのコンストラクターです。 次に例を示します。

public class BloggingContext : DbContext
{
    public BloggingContext()
    {
        this.Configuration.ProxyCreationEnabled = false;
    }  

    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

EF では、プロキシによって行われることが何もない型に対してはプロキシが作成されないことに注意してください。 つまり、型をシールするか、型に仮想プロパティを持たせないことによって、プロキシを回避することもできるということです。

プロキシのインスタンスを明示的に作成する

new 演算子を使用してエンティティのインスタンスを作成した場合、プロキシ インスタンスは作成されません。 これは問題になるとは限りませんが、プロキシ インスタンスを作成する必要がある場合 (たとえば、遅延読み込みやプロキシの変更の追跡が機能するようにする場合) は、DbSetCreate メソッドを使用して、そうすることができます。 次に例を示します。

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Create();
}

派生エンティティ型のインスタンスを作成する場合は、ジェネリック バージョンの Create を使用できます。 次に例を示します。

using (var context = new BloggingContext())
{
    var admin = context.Users.Create<Administrator>();
}

Create メソッドでは、作成されたエンティティがコンテキストに追加またはアタッチされないことに注意してください。

エンティティのプロキシ型を作成しても、それが何もしないために価値がない場合、Create メソッドは、エンティティ型自体のインスタンスを作成するだけです。 たとえば、エンティティ型がシールされているか、仮想プロパティを持たない場合、Create はエンティティ型のインスタンスを作成するだけです。

プロキシ型から実際のエンティティ型を取得する

プロキシ型には、次のような名前が付いています。

System.Data.Entity.DynamicProxies.Blog_5E43C6C196972BF0754973E48C9C941092D86818CD94005E9A759B70BF6E48E6

このプロキシ型のエンティティ型は、ObjectContextGetObjectType メソッドを使用して確認できます。 次に例を示します。

using (var context = new BloggingContext())
{
    var blog = context.Blogs.Find(1);
    var entityType = ObjectContext.GetObjectType(blog.GetType());
}

GetObjectType に渡される型が、プロキシ型ではないエンティティ型のインスタンスであっても、エンティティの型が返されることに注意してください。 つまり、常にこのメソッドを使用して実際のエンティティ型を取得でき、型がプロキシ型であるかどうかを確認するための他のチェックは必要ないということです。