EF中的自动追踪与代理

自动追踪

EF框架会自动追踪实体的变化(通过比较实体的当前值与原始值)。

默认情况下,以下方法会自动触发实体变化的追踪

  • DbSet.Find
  • DbSet.Local
  • DbSet.Remove
  • DbSet.Add
  • DbSet.Attach
  • DbContext.SaveChanges
  • DbContext.GetValidationErrors
  • DbContext.Entry
  • DbChangeTracker.Entries

在循环添加大量实体时,可以通过关闭自动追踪功能提升性能,但在循环结束后要开启

using (var context = new BloggingContext()) 
{ 
    try 
    { 
        context.Configuration.AutoDetectChangesEnabled = false; 
 
        // Make many calls in a loop 
        foreach (var blog in aLotOfBlogs) 
        { 
            context.Blogs.Add(blog); 
        } 
    } 
    finally 
    { 
        context.Configuration.AutoDetectChangesEnabled = true; 
    } 
}

如果没有开启自动追踪功能,当实体变化时,无法自动更新到数据库中的。可以通过使用content.ChangeTracker.DetectChanges方法手动检测

      static void Main(string[] args)
        {
            using (var db=new SchoolEntities2())
            {
               db.Configuration.AutoDetectChangesEnabled = false;//禁用自动追踪
                var author = db.Authors.Find(1);
                author.Name = "112";
                db.ChangeTracker.DetectChanges();//手动检测实体
                Console.WriteLine(db.Entry(author).State);
                db.SaveChanges();
            }

            Console.WriteLine("ok");
            Console.ReadLine( );

在只读场景下,当查询大量数据时,可以通过禁用实体的追踪来提升性能

using (var context = new BloggingContext()) 
{ 
    // Query for all blogs without tracking them 
    var blogs1 = context.Blogs.AsNoTracking(); 
 
    // Query for some blogs without tracking them 
    var blogs2 = context.Blogs 
                        .Where(b => b.Name.Contains(".NET")) 
                        .AsNoTracking() 
                        .ToList(); 
}

代理

为 POCO 实体类型创建实例时,实体框架常常为充当实体代理的动态生成的派生类型创建实例。此代理重写实体的某些虚拟属性,从而自动执行操作。例如,此机制用于支持关系的延迟加载。

禁止创建代理

this.Configuration.ProxyCreationEnabled = false; 

显示创建代理实例

var blog = context.Blogs.Create(); 

从代理类型获取实际实体类型

var blog = context.Blogs.Find(1); 
var entityType = ObjectContext.GetObjectType(blog.GetType()); 

如果传递给 GetObjectType 的类型是非代理类型的实体类型的实例,则仍将返回实体的类型。这意味着,始终可以使用此方法获取实际的实体类型,而不用再检查类型是否是代理类型。

posted @ 2015-07-24 10:53  senki  阅读(675)  评论(0编辑  收藏  举报