使用代理

创建 POCO 实体类型的实例时,实体框架通常会创建动态生成的派生类型(充当实体的代理)的实例。 此代理替代实体的一些虚拟属性,以插入挂钩,用于在属性被访问时自动执行操作。 例如,此机制用于支持延迟加载关系。 本主题所介绍的方法同样适用于查询使用 Code First 和 EF 设计器创建的模型。

禁用代理创建

有时,防止实体框架代理实例很有用。 例如,序列化非代理实例比序列化代理实例要容易得多。 可通过清除 ProxyCreationEnabled 标志来禁用代理创建。 可在上下文的构造函数中执行此操作。 例如:

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

可使用 ObjectContext 中的 GetObjectType 方法找到此代理类型的实体类型。 例如:

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

请注意,如果传递给 GetObjectType 的类型是非代理类型的实体类型的实例,则仍返回实体类型。 这意味着你始终可使用此方法获取实际实体类型,而无需进行任何其他检查来查看该类型是否是代理类型。