一个偶然的机会,让我注意了EF 的Attach方法,于是深入了解让我大吃一惊
在我所参与的项目中所有的更新操作与删除操作都是把原对象加载出来后,再做处理,然后再保存到数据库,这样的操作不缺点在于每一次的操作都要对数据库进行两次操作,性能上有很大的问题,
于是Attach方法出场
在介绍Attach方法前先介绍与它相关的知识点
Attach方法:将给定实体以 System.Data.EntityState.Unchanged 状态附加到上下文中
从解释可以看出Attach方法主要目的就是把一个没有被dbContext跟踪的对象附加到dbCotext中使其被dbContext跟踪
1 对象上下文:DBContext 建一个新的上下文实例以创建将连接到的数据库的名称,默认状态是没有对任何对象跟踪的
2 实体状态: 在EF中对实体状会有4种状态:
2.1 Added:对象为新对象,并且已添加到对象上下文,但尚未调用
2.2 Deleted:对象已从对象上下文中删除
2.3 Detached:对象存在,但没有被跟踪。 在创建实体之后、但将其添加到对象上下文之前,该实体处于此状态
2.4 Modified:对象上的一个标量属性已更改,但尚未调用
2.5 Unchanged: 此对象尚未经过修改自对象附加到上下文中后,或自上次调用 (调用了SaveChange方法后所有的对象都改为Unchanged状态)
了解了相关的知识后就开始利用Attach方法改代码了
以上为原来的方法
using(Entities ctx = new Entities()) { Product product = ctx.Product.First(); //更新属性操作 ctx.SaveChange();
}
这种写法会产生两次对数据库的操作,改成Attach方法后如下
public void Update(Product product) { using(Entities ctx = new Entities) { //product 已前台更新后 ctx.Attach(product); ctx.ObjectStateManager.ChangeObjectState(entity,EntityState.Modified) ctx.SaveChange(); } } //EF 的处理方式如下 // 1 把对象附加到上下文中,并把状态改为Modified状态 // 2 调用Savechange方法时生成一段Update的SQL语句且Where 条件
// 为对象的主键Id,因为EF更新和删除都是根据主键ID来处理的
删除操作也是一样的,这里就只贴用Attach的处理方式了
public void Delete(Product product) { using(Entities ctx = new Entities) { Product entity = new Product{Id =1} ctx.Attach(entity); ctx.ObjectStateManager.ChangeObjectState(entity,EntityState.Deleted) ctx.SaveChange(); } } //前面说了EF是根据主键ID来处理的所以只要手动生成一个对象并把对应的ID赋值然后Attach到上下文中即可做到删除
相比项目中原来的方法,用Attach后对数据库的操作相应减少一次,性能上会有较大提升!