我们经常会遇到这样的问题:Update一个entity的部分数据时,通常需要new一个新的对象,然后事这新的对象Attach到Context中,代码如下所示:

 1         /// <summary>
 2         /// 只更新storedAddress数据中的DefaultAddress字段,更新为false
 3         /// 将默认地址改为不是默认地址
 4         /// </summary>
 5         /// <param name="storedAddress">地址信息</param>
 6         public void Update(StoredAddress storedAddress)
 7         {
 8             StoredAddress s = new StoredAddress { StoredAddressID = storedAddress.StoredAddressID };
 9             s.DefaultAddress = true;
10
11             _context.StoredAddresses.Attach(s);
12
13             s.DefaultAddress = false;
14
15             _context.SaveChanges();
16             _context.Detach(s);
17         }

_context.StoredAddresses.Attach(s);程序在这一句时往往会报出异常---Context 中已经存在有相同键的对象了,从而使得我们的部分更新不能成功。

经过分析,我们知道Context 中存在了一个对象,这个对象和我们new的对象s有相同的键,那么这个对象哪一个对象呢?通过代码我们不难看出这个对象是storedAddress,所以我们需要将storedAddress对象从Context 中Detach。我们的新代码如下:

 1          /// <summary>
 2         /// 只更新storedAddress数据中的DefaultAddress字段,更新为false
 3         /// 将默认地址改为不是默认地址
 4         /// </summary>
 5         /// <param name="storedAddress">地址信息</param>
 6         public void UpdateStoredAddressDefaultAddress(StoredAddress storedAddress)
 7         {
 8             //先撤销跟踪
 9             _context.Detach(storedAddress);
10
11             StoredAddress s = new StoredAddress { StoredAddressID = storedAddress.StoredAddressID };
12             s.DefaultAddress = true;
13
14             _context.StoredAddresses.Attach(s);
15
16             s.DefaultAddress = false;
17
18             _context.SaveChanges();
19             _context.Detach(s);
20         }

通常我们并不知道对象有没有Attach,下面提供一个方法来确定对象有没有Attach:

 1  public static bool IsAttached(this AllureContext context, object entity)
 2         {
 3             if (entity == null)
 4             {
 5                 throw new ArgumentNullException("entity");
 6             }
 7             ObjectStateEntry entry;
 8             if (context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry))
 9             {
10                 return (entry.State != System.Data.EntityState.Detached);
11             }
12             return false;
13         }

上面的方法调用为_context.IsAttached(storedAddress),这要求我们必须知道一个对象,然后才能判断这个对象有没有被Attached。这是比较普遍的解决办法,因为我们的storedAddress对象已经确定。如果我们将第一段代码改为:

 1         /// 只更新storedAddress数据中的DefaultAddress字段,更新为false
 2         /// 将默认地址改为不是默认地址
 3         /// </summary>
 4         /// <param name="id">需要修改的对象的id</param>
 5         public void Update(int id)
 6         {
 7
 8             StoredAddress s = new StoredAddress { StoredAddressID = id };
 9             s.DefaultAddress = true;
10
11             _context.StoredAddresses.Attach(s);
12
13             s.DefaultAddress = false;
14
15             _context.SaveChanges();
16             _context.Detach(s);
17         }

此时我们不知道有没有和s对象具有相同键的对象存在于Context,就算我们现在知道有个对象存在Context中,并且和s对象就有相同的键,但是我们不知到这个对象是什么,想要Detach这个对象,比较难了,因为只有一个id,我在网上找了一些办法:

  1. 办法一,直接写成Sql 语句,从而更新数据库中的对象
  2. 办法二,通过id从数据库中得到这个对象,然后Deatch这个对象

对于办法一,因为我们用的是EF,所以我们还想用EF的东西;对于办法二,我们需要在写一个方法,这个方法负责从数据库来得到这个对象,有点麻烦,性能方面,没有测试过,只是感觉麻烦。那么EF有么有给我们提供一些方法让我们通过仅有的信息得到这个对象呢,答案是有。方法如下

object originalItem = null;
            System.Data.EntityKey key = _context.CreateEntityKey("StoredAddresses", s);
            if (_context.TryGetObjectByKey(key, out originalItem))    
{
                _context.Detach(originalItem);         
}
注意:System.Data.EntityKey key = _context.CreateEntityKey("StoredAddresses", s);是EF5.0中的写法
EF6.0中的写法为System.Data.Entity.Core.EntityKey key = _context.CreateEntityKey("StoredAddresses", s);
这个方法放到这里有些难理解,我们可以将它放到我们的代码中:
 1         /// 只更新storedAddress数据中的DefaultAddress字段,更新为false
 2         /// 将默认地址改为不是默认地址
 3         /// </summary>
 4         /// <param name="id">需要修改的对象的id</param>
 5         public void Update(int id)
 6         {
 7
 8             StoredAddress s = new StoredAddress { StoredAddressID = id };
 9
10             object originalItem = null;
11             System.Data.EntityKey key = _context.CreateEntityKey("StoredAddresses", s);
12             if (_context.TryGetObjectByKey(key, out originalItem))
13             {
14                 _context.Detach(originalItem);
15             }
16
17              s.DefaultAddress = true;
18
19              _context.StoredAddresses.Attach(s);
20
21              s.DefaultAddress = false;
22
23              _context.SaveChanges();
24              _context.Detach(s);
25         }

我们通过EntityKey来获得这个对象,然后Detach这个对象,随后再Attach我们new的对象s,就可以修改数据库了。此方法中要注意CreateEntityKey()的用法,第一个参数entitySetName,注意名称要和 Navigation Properties的名称一样,具体详见http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.createentitykey.aspx

好了,我们的修改已经完成。

补充一下,我们的DBcontext实现为:

public partial class Context : ObjectContext

{

//具体实现

}

而不是DbContext。

这是两者最根本的区别:ObjectContext是一种模型优先的开发模式,DbContext是代码优先的开发模式。

所以有些方法是不同的,比如_context.Entry()方法在ObjectContext中是没有的。

转载于:https://www.cnblogs.com/zjf1987/p/3227239.html

Entity Framework 数据部分更新之Attach Detach相关推荐

  1. Entity Framework 数据并发访问错误原因分析与系统架构优化

    本文主要记录近两天针对项目发生的数据访问问题的分析研究过程与系统架构优化,我喜欢说通俗的白话,高手轻拍 1. 发现问题 系统新模块上线后,使用频率较高,故在实际使用和后期的问题重现测试中,产生了一下系 ...

  2. .net core Entity Framework 与 EF Core

    重点讲 Entity Framework Core ! (一)Entity Framework 它是适用于.NET 的对象关系映射程序 (ORM),现在的EF6已经是久经沙场,并经历重重磨难,获得一致 ...

  3. Entity Framework Core介绍(1)

    介绍 Entity Framework (EF) Core 是轻量化.可扩展和跨平台版的常用 Entity Framework 数据访问技术. EF Core 可用作对象关系映射程序 (O/RM),以 ...

  4. Entity Framework学习三:查询、插入、更新和删除操作

    1.LINQ过滤数据  var query = from person in context.Peoplewhere person.FirstName.StartsWith("a" ...

  5. Entity Framework CodeFirst数据迁移

    原文:Entity Framework CodeFirst数据迁移 前言 紧接着前面一篇博文Entity Framework CodeFirst尝试. 我们知道无论是"Database Fi ...

  6. 关于Entity Framework自动关联查询与自动关联更新导航属性对应的实体注意事项说明...

    一.首先了解下Entity Framework 自动关联查询: Entity Framework 自动关联查询,有三种方法:Lazy Loading(延迟加载),Eager Loading(预先加载) ...

  7. Entity Framework技术系列之1:数据访问技术概述

    前言 .NET Framework自2002年发布以来,已经历了十来个年头.相应的,.NET平台上的数据访问技术也在不断发展,从最基础的ADO.NET,到SqlHelper简单帮助类,到DAAB(Da ...

  8. Entity Framework 6 Recipes 2nd Edition(9-1)译-用Web Api更新单独分离的实体

    第九章 在N层结构的应用程序中使用EF 不是所有的应用都能完全地写入到一个单个的过程中(就是驻留在一个单一的物理层中),实际上,在当今不断发展的网络世界,大量的应用程序的结构包含经典的表现层,应用程, ...

  9. .net core引用错误的Entity Framework而导致不能正常迁移数据的解决办法

    本人刚学.net core,因此在学习过程中会遇上许许多多的坑.每一位初学者最大的问题在于资料的查看不仔细或是没有正确理解里面的内容,导致在后面自己在不知道错误的情况下做了一个小动作.对于完全没有理解 ...

最新文章

  1. 网页后门工具laudanum
  2. Microsoft CryptoAPI加密技术(一)
  3. flink的savepoint实验-java
  4. 2019.5.8_此书真乃宝书也_从定位参数到仅限关键字参数
  5. Django学习笔记(4)
  6. 腾讯35k招.NET Core开发,深扒这些技术要求 真的很难吗?
  7. Kafka基础系列第1讲:Kafka的诞生背景及应用
  8. php使用 js格式解析,JavaScript解析JSON格式数据的方法示例
  9. lua html 转义字符,Lua中特殊字符过滤(UTF8编码)
  10. DataSnap 2009 系列之三 (生命周期篇)
  11. 平面一般力系最多可以求解_利用平面一般力系的平衡方程最多可求解几个未知量。( )...
  12. BScroll warn 】EventEmitter has used unknown event type: “pullingUp“解决方法:看bs文档
  13. iOS13微信收款到账语音提醒开发总结
  14. Android ViewPage使用
  15. html5酷炫动画效果网站,html5 WebGL酷炫网页动画特效
  16. 阿里云Centos8 yum报错Failed to synchronize cache for repo ‘BaseOS‘解决方案,通过换文件的方式来解决。
  17. java工程师面试题大全100%公司笔试题你都能碰到几个
  18. kali 2.0 安装搜狗输入法 troubleshooting
  19. ai人工智能_药物发现中的人工智能
  20. linux设备驱动程序第二版 序言

热门文章

  1. Hbuilder实用技巧
  2. 关于js选项卡的一些问题
  3. 【聊透SpringMVC】自学java和三大框架要多久
  4. 升职加薪必看!如何试出一个Java开发者真正的水平
  5. 基于Pytorch再次解析使用块的现代卷积神经网络(VGG)
  6. 【PAT (Advanced Level) Practice】1149 Dangerous Goods Packaging (25 分)
  7. 【django轻量级框架】在线视频教育系统设计与实现
  8. 公共基础选择题—关系代数和范式
  9. python初级_python--的初级了解
  10. 鸿蒙系统2.0什么时候上线,华为官方:鸿蒙系统2.0上线,手机能否搭载鸿蒙操作系统?...