使用代理
创建 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 运算符创建实体的实例,系统不会创建代理实例。 这可能并不是个问题,但是如果你需要创建一个代理实例(例如,以便延迟加载或代理更改跟踪可以工作),则可使用 DbSet
的 Create
方法来实现。 例如:
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
的类型是非代理类型的实体类型的实例,则仍返回实体类型。 这意味着你始终可使用此方法获取实际实体类型,而无需进行任何其他检查来查看该类型是否是代理类型。