EntityFramework Add方法与Attach区别
一 先发问。
问题:在使用EF过程中,能否有一个方法可以直接执行传入的SQL语句。纠结的只找到了调用存储过程的方法,难道要SqlHelper.cs?
二 友情提示
本文内容参考自MSDN。
三 言归正传
平时使用MVC 开发时,在CRUD相关的Action当中,都会有在最后调用一句代码:
db.SaveChanges();// Entities db=new Entities()
这个方法会根据当前欲操作的实体(Entity)所处的状态(State)与数据库交互。单单从名字上可以看出这个方法是为了“保存改变”,在现实中,一位你好久没见的朋友有可能会这样说:“小王啊,好久没见,你变胖了,是不是赚大钱了,生活安逸喽?”姑且不论你是不是张的长胖了,还是赚大钱了,这里面“胖”就是用来表征你当前所处的状况的一个描述。在命名空间System.Data当中,也有一个描述实体所处状态的枚举类型EntityState:
// 摘要:
// 实体对象的状态。
[Flags]
public enum EntityState
{
// 摘要:
// 对象存在,但未由对象服务跟踪。在创建实体之后、但将其添加到对象上下文之前,该实体处于此状态。通过调用 System.Data.Objects.ObjectContext.Detach(System.Object)
// 方法从上下文中移除实体后,或者使用 System.Data.Objects.MergeOption.NoTrackingSystem.Data.Objects.MergeOption
// 加载实体后,该实体也会处于此状态。
Detached = ,
//
// 摘要:
// 自对象加载到上下文中后,或自上次调用 System.Data.Objects.ObjectContext.SaveChanges() 方法后,此对象尚未经过修改。
Unchanged = ,
//
// 摘要:
// 对象已添加到对象上下文,但尚未调用 System.Data.Objects.ObjectContext.SaveChanges() 方法。对象是通过调用
// System.Data.Objects.ObjectContext.AddObject(System.String,System.Object)
// 方法添加到对象上下文中的。
Added = ,
//
// 摘要:
// 使用 System.Data.Objects.ObjectContext.DeleteObject(System.Object) 方法从对象上下文中删除了对象。
Deleted = ,
//
// 摘要:
// 对象已更改,但尚未调用 System.Data.Objects.ObjectContext.SaveChanges() 方法。
Modified = ,
}
这五种状态分别是:Detached-游离;UnChanged-没有变化;Added-添加;Deleted-删除;Modified-编辑。Detached状态下的Entity不会被上下文(context)所捕获(track),比如说下面这种情况下:
public JsonResult Edit(UserModel source)
{
if (this.ModelState.IsValid)
{
User destination = new User(); UserToEntity(source, destination);
destination.ID = source.ID;
db.Entry(destination).State = System.Data.EntityState.Modified;
db.SaveChanges();
return Json(new { isok = true, tip = "修改成功" });
}
else
{
return Json(new { isok = false, tip = "添加用户失败" });
}
}
在db.Entry(destination)……这句代码执行之前,destination的State状态就是游离。
除了游离状态,剩下的四种状态均会被上下文所捕获,具体意思也很好理解。
当SavaChanged()方法执行期间,他会查看当前Entity的EntityState的值,决定是去新增(Added)、修改(Modified)、删除(Deleted)、什么也不做(UnChanged)。
回到正题,DbContext类的Add()方法的作用就是将一个Entity的State修改为Added,这样在SavaChanged()方法就会将实体新增到数据库当中。而Attach在 微软的中文翻译中是附加,不同于Add方法的添加,她是将一个处于Detached的Entity附加到上下文,而附加到上下文后的这一Entity的State为UnChanged,所以在下面的代码中,需要将obj的State修改为Modified:
/// <summary>
/// 更新Entity(注意这里使用的傻瓜式更新,可能性能略低)
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
public virtual bool Update(T entity)
{
var obj = db.Set<T>();//新建一个泛型DbSet
obj.Attach(entity);//附加到上下文
db.Entry(entity).State = System.Data.EntityState.Modified;//修改State
return db.SaveChanges() > ;
}
新建的obj Entity因为出于Detached,所以我们需要先附加后修改其EntityState;
搞清楚这点,完成添加功能的Action 是不是可以这样写呢:
public virtual bool Add(T entity)
{
var obj = db.Set<T>();
obj.Attach(entity);
db.Entry(entity).State = System.Data.EntityState.Added;
return db.SaveChanges() > ; }
同样的,删除的Remove方法也可以不用,转而修改其State为Deleted。
最后,那就可以用Action完成Add或Update的功能:
public void InsertOrUpdate(Blog blog)
{
using (var context = new BloggingContext())
{
context.Entry(blog).State = blog.BlogId == ?
EntityState.Added :
EntityState.Modified; context.SaveChanges();
}
}
以往增加删除都是用一个相同的部分视图加上不同的控制器实现,现在只需要在一个控制器就能实现增加和修改了。
四 Context
上下文是一个不太好描述清楚的东东,我是这样简单理解的:有一些方法,在参数中不方便,也不可能获取到的东东(请原谅我这样形容),就可以将其存储在上下文中。比如我这个方法需要知道当前用户是谁,需要知道这次请求来自于哪一个Controller,就可以调用不同的Context获得。在MVC中有很多上下文类,列如这篇博文总结的MVC上下文;
EntityFramework Add方法与Attach区别的更多相关文章
- C#用Open与Add方法打开word文档的区别
C#打开word文档常用有两种方法:Add与Open. Microsoft.Office.Interop.Word._Document doc = (Document)appWord.Document ...
- docker Dockerfile指令ADD和COPY的区别,添加目录方法
docker Dockerfile指令ADD和COPY的区别,添加目录方法 ADD指令的功能是将主机构建环境(上下文)目录中的文件和目录.以及一个URL标记的文件 拷贝到镜像中.其格式是: ADD 源 ...
- Queue接口分析:add和offer区别,remove和poll方法到底啥区别
Queue接口: public interface Queue<E> extends Collection<E> { /* * add方法,在不违背队列的容量限制的情况,往队列 ...
- List的add方法与addAll方法的区别、StringBuffer的delete方法与deleteCharAt的区别
List的add方法与addAll方法 区别 add add是将传入的参数作为当前List中的一个Item存储,即使你传入一个List也只会另当前的List增加1个元素 addAll addAll是传 ...
- Fragment 的 replace 和 add 方法的区别?
Fragment 本身并没有 replace 和 add 方法,这里的理解应该为使用 FragmentManager 的 replace 和 add 两种方法切换 Fragment 时有什么不同.我们 ...
- LinkedBlockingQueue的put,add跟offer的区别
LinkedBlockingQueue的put,add和offer的区别 最近在学习<<Java并发编程实践>>,有很多java.util.concurrent包下的新类.Li ...
- 在 VS 类库项目中 Add Service References 和 Add Web References 的区别
原文:在 VS 类库项目中 Add Service References 和 Add Web References 的区别 出身问题: 1.在vs2005时代,Add Web Reference(添加 ...
- LinkedBlockingQueue的put,add跟offer的区别(转)
LinkedBlockingQueue的put,add和offer的区别 最近在学习<<Java并发编程实践>>,有很多java.util.concurrent包下的新类.Li ...
- 队列Queue中add()和offer()的区别?
区别:两者都是往队列尾部插入元素,不同的时候,当超出队列界限的时候,add()方法是抛出异常让你处理,而offer()方法是直接返回false
随机推荐
- 学习Slim Framework for PHP v3 ( 二)
昨天说到能够成功将本地的URL通过在index.php 中添加get(pattern,clouser)路由到指定的处理类中,处理后(这里指存入数据库中),然后返回response在浏览器中显示. 昨天 ...
- C# 中 static 的用法
说明1: 表示静态的关键字说明此对象在应用中只存在一份 说明2:C# 是面向对象的程序设计语言,每一个函数都属于一个类. 当 一个方法被声明为Static时,这个方法是一个静态方法,编译器会在编译时保 ...
- 二十一、Android上常见度量单位【xdpi、hdpi、mdpi、ldpi】解读
术语和概念 屏幕尺寸 屏幕的物理尺寸,以屏幕的对角线长度作为依据(比如 2.8寸, 3.5寸). 简而言之, Android把所有的屏幕尺寸简化为三大类:大,正常,和小. 程序可以针对这三种尺寸的屏幕 ...
- vim 高级使用技巧
前言:逃离windows有很长时间了,特别是当今android盛行的时代,我们没有理由不选择ubuntu作为编译开发android之首选.其实操作系统只是我们使用的一个工具, windows也好lin ...
- ASP.NET MVC3 301永久重定向实现程序
使用 ASP.NET 又喜欢跟进新技术的朋友可能已经知道,在 ASP.NET 4.0 中增加了 Response.RedirectPermanent() 方法来实现永久重定向,方法的作用在注释中解释的 ...
- 利用 NUget包 EPPlus 实现数据导出到Excel(适用于DTcms)
首先安装EPPlus 包
- 《NFS文件共享服务的搭建》RHEL
首先要清楚一点:NFS服务的共享是建立在linux和linux之间的. 配置任何服务之前我们要做的2件事: iptables -F setenforce 0 NFS服务内核防火墙影响不大,主要 ...
- c++11: less的用法
less主要是重载了operator()方法,用来比较lhs 和 rhs std::less::operator() bool operator()(const T &lhs, const T ...
- Linux进程间通信方法总结
①匿名管道(pipe) 匿名管道(pipe)管道是一种半双工的通信方式,数据只能单向流动.如果要进行双工通信,需要建立两个管道.管道只能在具有亲缘关系的进程间使用,例如父子进程或兄弟进程. ②有名管道 ...
- MQTT开发小记(一)
最近在协助公司硬件组进行MQTT协议的嵌入式SDK包开发. 简述一下MQTT MQTT简单的来说是一种订阅/发布模式的通信形式,一般分为客户端和服务器端. MQTT服务器端可以简单理解为一个消息中转站 ...