Entity Framework使用EntityState和Attach来保存数据变化以及更新实体的个别字段

在使用Entity Framework作为ORM来存取数据的过程中,最常规的操作就是对数据对象的更新。本文将会包含如何Attach Entity到一个数据Context中,以及如何使用EntityState字段状态来保存数据变化。

文本参考了如下两篇文章:

https://msdn.microsoft.com/en-us/data/jj592676

https://stackoverflow.com/questions/30987806/dbset-attachentity-vs-dbcontext-entryentity-state-entitystate-modified


当要做数据更新时,我们通常会使用如下代码:

1 context.Entity(entity).State = EntityState.Modified;

2 context.SaveChanges(); 

 

context.Entity(entity).State = EntityState.Modified; 这句代码不仅会将entity attaching到当前的context中,而且还会告诉context这个entity已经发生了变化。当执行savechanges()时,EF会使用update语句将entity中所有的字段全部更新。

上面的这种方式虽然方便,但是在某些时候也会带来效率上的浪费。如果我们只是想更新其中的某个或者某些字段而不是全部字段的时候,使用这种方式就不必要了。那么该如何操作,才能让Entity Framework精确的保存我们想要变更的字段呢?我们可以使用Dbset.Attach(entity)。

Dbset.Attach(entity)只是会将entity attach到context中,而不会告诉context这个实体已经发生修改。所以如果你只是attach entity而之后不做任何处理的话,savechanges()操作将不会有任何变化。所以它和context.Entity(entity).State = EntityState.Unchanged是相同的。要保存个别字段,需要将entity更改之后再调用savechanges方法。请参见下面的代码样例。

 

代码样例:

下面使我们定义的实体以及它们的Context:

 

 1 public class Department
 2 {
 3 public int Id {get;set;}
 4 public string Name {get;set;}
 5 public DateTime CreateTime {get;set;} 
 6 
 7 public int DepLeadID { get; set; }
 8 
 9 [ForeignKey("DepLeadID")]
10 public DepLead Lead {get;set;}
11 }

 

1 public class DepLead
2 {
3 public int Id {get;set;}
4 public string name {get;set;}
5 public int age {get;set;}
6 }

 

 1 public class Context : DbContext
 2     {
 3         public Context() : base("XXX")
 4         {
 5         }
 6         public DbSet<Department> Departments { get; set; }
 7         public DbSet<DepLead> DepLeads { get; set; }
 8 
 9         protected override void OnModelCreating(DbModelBuilder modelBuilder)
10         {
11             modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
12         }
13 
14     }

 

如果我们使用如下方式更新数据:

context.Entity(someDepartment).State = EntityState.Modified;
context.SaveChanges();

那么相当于执行如下SQL

UPDATE department
SET Name = 'xxx',CreateTime = 'XXX', DepLeadID = 'XXX'
where Id = '1000'; -- the id of someDepartment

上面的这种方式,不会自动的检查字段是否变化,而是把所有的字段全部按照someDepartment中的值进行更新,即使没有任何变化。

而另外一种Attach的方式在更新上就会更加灵活。

context.Departments.Attach(someDepartment);
someDepartment.Name = 'XXX';
context.SaveChanges();

以上片段会执行下面语句:

UPDATE department
set Name = 'XXX'
where Id = '1000'

假如你想指定实体someDepartment中哪些字段是已经更改的状态,可以按如下代码:

context.Departments.Attach(someDepartment);
context.Entry(someDepartment).Property("Name").IsModified = true;
context.SaveChanges();

这样它也会像上面的SQL那样将Name字段更新。

 

posted @ 2018-04-05 15:50  何事惊慌?  阅读(326)  评论(0编辑  收藏  举报