ADO.NET EF 中的实体修改方法

http://www.cnblogs.com/zfz15011/archive/2010/05/30/1747486.html

1.传统修改模式,看下列代码

using (NorthwindEntities context = new NorthwindEntities())
{
    Region region = context.Region.FirstOrDefault(v => v.RegionID == 4);
    region.RegionDescription = "Test";
    context.SaveChanges();
}

监控SQL语句:

SQL1:SELECT TOP 1 [Extent1].[RegionID] AS [RegionID], [Extent1].[RegionDescription] AS [RegionDescription]FROM [dbo].[Region] AS [Extent1]WHERE 4 = [Extent1].[RegionID]
SQL2:exec sp_executesql N‘update [dbo].[Region]set [RegionDescription] = @0where ([RegionID] = @1)‘, N‘@0 nchar(4),@1 int‘, @0 = N‘Test‘, @1 = 4

从这里例子中可以看出使用“传统模式”的数据更新,必须先要执行一次查询,将获取要更新的实体对象,在看下面的例子:

Region region;
using (NorthwindEntities context = new NorthwindEntities())
{
    region = context.Region.FirstOrDefault(v => v.RegionID == 4);
}
using (NorthwindEntities context = new NorthwindEntities())
{
    region.RegionDescription = "Test";
    context.SaveChanges();
}

更新是不会执行的,因为实体不再 执行 SaveChanges 的对象中所以 当我们更新一个 不再当前连接中的对象是必须要先执行查询获取这个对象才能对其更新,如下:

Region region;
using (NorthwindEntities context = new NorthwindEntities())
{
    region = context.Region.FirstOrDefault(v => v.RegionID == 4);
}
using (NorthwindEntities context = new NorthwindEntities())
{
    Region newRegion = context.Region.FirstOrDefault(v => v.RegionID == region.RegionID);
    region.RegionDescription = "Test";
    context.SaveChanges();
}

2.使用ApplyPropertyChanges 修改实体

Region region;
using (NorthwindEntities ne = new NorthwindEntities())
{
    //利用EntityObject.Execute(MergeOption.NoTracking),等效于使用ObjectContext.Dettach(EntityObject)
    //查询并分离对象
    region = ne.Region.Execute(MergeOption.NoTracking).Where(v => v.RegionID == 1).FirstOrDefault();
}
//修改分离的值
region.RegionDescription = "TestTest1";
//使用分离的对象 order 更新 
using (NorthwindEntities context = new NorthwindEntities())
{
    //将数据载入到context中以便更新
    context.GetObjectByKey(region.EntityKey);
    //使用order 更新 context中的对应对象
    context.ApplyPropertyChanges(region.EntityKey.EntitySetName, region);
    context.SaveChanges();
}

监控SQL语句:

SQL1:exec sp_executesql N‘SELECT [Extent1].[RegionID] AS [RegionID], [Extent1].[RegionDescription] AS [RegionDescription] FROM [dbo].[Region] AS [Extent1] WHERE [Extent1].[RegionID] = @p0‘, N‘@p0 int‘, @p0 = 1
SQL2:exec sp_executesql N‘update [dbo].[Region] set [RegionDescription] = @0where ([RegionID] = @1) ‘, N‘@0 nchar(9),@1 int‘, @0 = N‘TestTest1‘, @1 = 1

ApplyPropertyChanges在MSDN的解释是“将已分离对象的属性更改应用于已附加到对象上下文的对象。”其实说白了就是 拿旧对象去更新新对象,我们可以看出 使用“ApplyPropertyChanges 修改实体”方法修改实体与 使用“传统模式”是一样的,都是必须先执行一次查询,获取更新的对象,但是 ApplyPropertyChanges方法的特殊之处是,该方法会拿内存中的对象(新对象)和当前连接中的对象(旧对象)对比,自动生成对应字段修改的Update语句,如果内存中的对象与当前连接中的对象完全相等(每个字段的值都相等),将不生成响应的Update。当我们再次执行 上述代码观察监控到了SQL语句,你会发现只监控到SQL1,不会得到SQL2。

3.使用Attach与SetModifiedProperty修改实体

using (NorthwindEntities context = new NorthwindEntities())
{
    Region region = context.Region.FirstOrDefault(v => v.RegionID == 4);
    context.Detach(region);
    region.RegionDescription = "因为测试";

context.Attach(region);
    var newRegion = context.ObjectStateManager.GetObjectStateEntry(region);
    newRegion.SetModified();
    newRegion.SetModifiedProperty("RegionDescription");

context.SaveChanges();
}

监视SQL语句:

exec sp_executesql N‘update [dbo].[Region]set [RegionDescription] = @0where ([RegionID] = @1)‘, N‘@0 nchar(4),@1 int‘, @0 = N‘因为测试‘, @1 = 4

使用该方法,可以将不再当前连接集合中的实体使用Attach方法加入到当前集合中 在使用 SetModifiedProperty 来设置修改字段,使用该方法不必再执行查询将数据读入当前连接对象才能修改

时间: 2024-12-21 08:10:46

ADO.NET EF 中的实体修改方法的相关文章

EF6基础系列(五)---EF中的实体关系

这一节将总结EF是怎么管理实体之间的关系.EF与数据库一样支持三种关系类型:①一对一 ,②一对多,③多对多. 下边是一个SchoolDB数据库的实体数据模型,图中包含所有的实体和各个实体间的关系.通过设计器我们很容易看出实体间的对应关系 1.一对一 如上图,Student和StudentAddress具有一对一的关系(零或一).一个学生只能有一个或零个地址.实体框架将Student实体导航属性添加到StudentAddress实体中,将StudentAddress实体导航属性添加到Student

在EF中使用MySQL的方法及常见问题

有时需要在网上租用空间或数据库,Mysql成本低一些,所以想将sql server转成mysql…… 注意:在安装Mysql时要选择文字集为utf8,否则将不能使用中文(当前也可以在创建数据库时使用utf8,不过我不知道在ef生成数据库时如何设置,希望高手指点) 一.在项目中引用mysql的EF包 通过NuGet包管理器安装:EntityFramework6.1.3.MySql.Data.Entity6.9.8 也可以用nuget的命令行加入: Install-Package MySql.Dat

EF中的实体类型(EF基础系列篇6)

EF中有两种类型的实体:POCO Entity和dynamic proxy entity. POCO Entity (Plain Old CLR Object) POCO class是一个类,它不依赖任何.NET framework的基类,它就像任何其他的普通类一样,这也是为什么被称之为“Plain Old CLR Object”的原因: 这些由实体数据模型生成的POCO实体支持大多数的增删查改的功能.下面是一个Studnet POCO实体: public class Student { pub

EF中自编写SQL脚本查询结果(适用于复杂SQL逻辑提高查询效率)

前不久项目开发过程中,使用的是Entity Framework做数据处理.因为本人也不是对EF太有研究,只是会用而已,但是在一次需要查询的结果需要关联3.4个表来查询出来结果,并且对查询效率也有要求.但是个人觉得遇到这样的情况还是使用原始SQL语句来查询更为可控(或许EF中有更好的方法可以解决此类问题,但恕本人愚笨只想到了这种方法).就又自己扩展出一个方法,用来专门查询自定义编写的SQL语句.代码如下: public List<T> ExecuteStoreQuery(string comma

EF+泛型修改方法(查询修改和不查询修改)

最近在做项目用到了@邹华栋老师的EF直接更新数据(不需查询)的方法. 但是如果我们想修改的对象前面被查询过了的话会出一个<ObjectStateManager 中已存在具有同一键的对象.ObjectStateManager 无法跟踪具有相同键的多个对象>的错误.解决方法是查询的时候加AsNoTracking无跟踪查询.但是我需要实体被EF context追踪,所以加AsNoTracking是不行的. 然后花了三个多小时就改写了方法,改方法可以修改查询过的或是没查询过的对象但是需要主键名.不知道

《Entity Framework 6 Recipes》中文翻译系列 (40) ------ 第七章 使用对象服务之从跟踪器中获取实体与从命令行生成模型(想解决EF第一次查询慢的,请阅读)

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 7-5  从跟踪器中获取实体 问题 你想创建一个扩展方法,从跟踪器中获取实体,用于数据保存前执行一些操作. 解决方案 假设你有如图7-7所示的模型. 图7-7. 包含实体Technician和ServiceCall的模型 在这个模型中,每个技术员(technician)都有一些业务服务请求(service call),业务服务请求包含联系人姓名,问题.使用代码清单7-4,创建一个扩展方法获取

EF中修改对象的值的问题。。。(字段超级多的时候)

一般EF中修改单个对象的值,我是这样处理的. 如:DBEntities db=new DBEntities(); student stu = db.student.firstOrdefault(m=>m.id==id); stu.name="sb"; stu.age=11; ...... db.SaveChange(); 如果字段少的情况下,没什么问题(EF中好像还有一个修改的方法,先不管它). 如果200个字段呢?你还去一个个.属性么? 这个问题我用反射可以解决.具体方法见小弟

关于在EF中通用方法

在EF中有时需要用到一些通用类,在后端模型和前端模型在某些场合需要模型分离, 例如数据模型和试图模型中用到的增删改功能 public class DBHelper<V, T>        where V : class ,new()        where T : class ,new()    { public Result Update(V Entity)        {            using (var db = new DbContext())            {

如何防止参数中的实体对象被修改

近段在项目中,判断需要循环嵌套循环,并在循环中确定需要新建的数据.其实就是,我们有个树结构,需要从DB中查询所有的某个层级节点的数据,并循环每条记录,为每条记录依据一个xml来判断该节点下哪些子节点缺失,缺失的话就新增. 每次循环中需要构造一些属性.结果在对Model对象未克隆时,出现属性值混乱.所以我后来就干脆用了克隆方法. -----------------------------------我是正文分割线-------正文分割线-------分割线---------线-----------