Entity Framework 数据部分更新之Attach &&Detach
来源:互联网 发布:原来在淘宝上买的基金 编辑:程序博客网 时间:2024/05/16 01:09
我们经常会遇到这样的问题: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,我在网上找了一些办法:
- 办法一,直接写成Sql 语句,从而更新数据库中的对象
- 办法二,通过id从数据库中得到这个对象,然后Deatch这个对象
对于办法一,因为我们用的是EF,所以我们还想用EF的东西;对于办法二,我们需要在写一个方法,这个方法负责从数据库来得到这个对象,有点麻烦,性能方面,没有测试过,只是感觉麻烦。那么EF有么有给我们提供一些方法让我们通过仅有的信息得到这个对象呢,答案是有。方法如下
System.Data.EntityKey key = _context.CreateEntityKey("StoredAddresses", s);
if (_context.TryGetObjectByKey(key, out originalItem))
_context.Detach(originalItem);
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
好了,我们的修改已经完成。
<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
- Entity Framework 数据部分更新之Attach &&Detach
- MVC5 Entity Framework学习之更新相关数据
- Entity Framework不能成功更新数据
- Entity Framework 部分应用
- Entity Framework 5.0系列之数据操作
- Entity Framework 5.0系列之数据操作
- Entity Framework 5.0系列之数据操作
- Entity Framework 5.0系列之数据操作
- Entity Framework 5.0系列之数据操作
- attach和detach
- Attach、Detach和DeleteObject
- attach和detach
- Attach、Detach和DeleteObject
- Attach、Detach和DeleteObject
- Attach、Detach和DeleteObject
- db2 - DETACH & ATTACH PARTITION
- Attach、Detach和DeleteObject
- attach和detach区别
- 时钟
- 得到java异常printStackTrace的详细信息
- Android4.0内存Dex数据动态加载技术
- 动态规划(4)最大连续子串问题
- C/C++中static关键字详解
- Entity Framework 数据部分更新之Attach &&Detach
- RTSP 请求响应历程举例
- 文件的上传与下载
- [android]JNI Examples for Android
- mysql基础
- 七月份学习的一些零散知识点
- RTSP会话
- 新手用WPF山寨QQ管家7.6(三)
- HTML颜色代码表