先来看一段错误提示:The instance of entity type ‘XXXX’ cannot be tracked because another instance with the same key value for {‘Key’} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
这里面的"XXXX"可能是任意一个实体模型的名称,“Key"则是这个实体的Key字段。
出现这个错误的原因是试图更新某个实体时,拥有相同Key的另一个实体也被EF Core tracked了。看一下这段代码:

[HttpPost]
public async Task<IActionResult> TestTracked(DeviceType deviceType)
{try{//type这个实体被EF Core trackedvar type = await context.DeviceTypes.FindAsync(deviceType.Id);//准备更新deviceType实体,但type实体的key与deviceType的key相同,也就是同一个Key的实体被多次tracked,出现本文开头说的错误context.Update(deviceType);await context.SaveChangesAsync();}catch (Exception ex){Console.WriteLine(ex);}return new JsonResult(new { success = true });
}

要解决这个问题很简单,从linq查询返回实体时指定不跟踪实体就行了。

//把原来的代码:var type = await context.DeviceTypes.FindAsync(deviceType.Id); 改成下面这样
var type = await context.DeviceTypes.AsNoTracking().FirstOrDefaultAsync(d => d.Id == deviceType.Id);

AsNoTracking()方法就是起这个作用。

但是我今天碰到一个很奇怪的多次tracked问题。
我有一个实体Point,其中包含一个导航属性Devices,这是一个List<Device>,也就是Point实体和Device实体是一对多的关系。Device实体中又包含了几个外键。现在我向服务器提交json数据,准备更新一个Point实体,数据类似如下:

{"pointId": 1,"pointName": "测试点","devices": [{"deviceId": 1,"modelId", 1,"supplierId: 1,},{"deviceId": 2,"modelId", 2,"supplierId: 1,}]
}

Device实体中的modelId和supplierId都是外键。
结果在context.Update(point)时,出现实体被多次跟踪的错误,错误中实体名是SupplierSupplierDevice的外键表。在整个更新的过程中,我没有对Supplier实体做任何查询和更新的动作。所以这个错误就出现的比较古怪了。

经过反复跟踪调试,终于找到问题原因。
在服务器端获取Point实体时,为了在客户端展现SupplieName,我使用了Include和ThenInclude方法:

var point = await context.Points.Include(p => p.Devices)                    //获取Devices集合数据.ThenInclude(p => p.DeviceModel)         //获取Device实体的关联实体DeviceModel数据.Include(p => p.Devices).ThenInclude(p => p.Supplier)             //获取Device实体的关联实体Supplier的数据.FirstOrDefaultAsync(p => p.Id == id);

返回到客户端的json对象类似以下:

{"pointId": 1,"pointName": "测试点","devices": [{"deviceId": 1,"modelId", 1,"deviceModel": { deviceMode对象,略 },"supplierId: 1,"supplier": { supplier对象, 略 }},{"deviceId": 2,"modelId", 2,"deviceModel": { deviceMode对象,略 },"supplierId: 1,"supplier": { supplier对象, 略 }}]
}

客户端更新时,修改了上面json对象的部分字段,再把json对象提交到服务器,因此json对象中的DeviceModel和Supplier对象都不为null,当使用EF Core的Update方法时,因为多个Device对象中的Supplier实体的Key相同,就出现多次tracked错误。在这个案例中,因为每个Device的ModelId都不同,所以没有报DeviceModel实体被多次tracked错误。
找到问题原因,解决就简单了,在调用Update方法之前,把每个Device对象中关联实体都设为null就可以了。

foreach (var device in point.Devices)
{//把所有外键实体设为null,避免出现多次tracked的错误device.DeviceModel = null;device.Supplier = null;
}

也可以在客户端转换json字符串时处理:

$("#devices input").each((_, item) => {devices.push(JSON.parse($(item).val(), (key, value)=>{switch(key){case "deviceModel":case "supplier":return null;default:return value;}}));
})

当然,从代码结构上来讲,在服务器端处理比较好。

关于EF Core中同一个实体被多次tracked的问题相关推荐

  1. [小技巧]EF Core中如何获取上下文中操作过的实体

    原文地址:https://www.cnblogs.com/lwqlun/p/10576443.html 作者:Lamond Lu 源代码:https://github.com/lamondlu/EFC ...

  2. 第五节:EF Core中的三类事务(SaveChanges、DbContextTransaction、TransactionScope)

    一. 说明 EF版本的事务介绍详见: 第七节: EF的三种事务的应用场景和各自注意的问题(SaveChanges.DBContextTransaction.TransactionScope). 本节主 ...

  3. EF Core中高效批量删除、更新数据的Zack.EFCore.Batch发布三个新特性

    Zack.EFCore.Batch是一个支持在Entity Framework Core中高效删除和更新数据的开源库.我们知道,EF Core中不支持高效的删除和更新数据,所有的更新和操作都是逐条数据 ...

  4. EF Core中避免贫血模型的三种行之有效的方法(翻译)

    [Paul Hiles: 3 ways to avoid an anemic domain model in EF Core :https://www.devtrends.co.uk/blog/3-w ...

  5. EF Core 中实现 动态数据过滤器

    前言 在项目开发中,我们很多时候都会设计  软删除.所属用户 等等一系列字段 来方便我们在业务查询的时候进行各种过滤 然后引申的问题就是: 在业务查询的时候,我们要如何加上这些条件?或者动态禁用某些查 ...

  6. ef core中如何实现多对多的表映射关系

    文档:https://docs.microsoft.com/en-us/ef/core/modeling/relationships class MyContext : DbContext{publi ...

  7. ef core select选择实体中的部分数据

    public User {public string Name { get; set; }public string Age { get; set; }public string Color { ge ...

  8. EF Core中关于System.Linq.Dynamic.Core的使用(转载)

    项目中经常用到组合条件查询,根据用户配置的查询条件进行搜索,拼接SQL容易造成SQL注入,普通的LINQ可以用表达式树来完成,但也比较麻烦.有个System.Linq.Dynamic.Core用起来比 ...

  9. ef linq 中判断实体中是否包含某集合

    我有一个需求,问题有很多标签,在查询时,需要筛选包含查询标签的一个集合(List<int>),以前的做法是先查询出来符合查询标签条件的标签id的结果集A,再查询问题时,加上判断是否包含该标 ...

  10. ef core中使用code first

    这个配置还是挺坑,照这个一步步做倒是可以 https://www.cnblogs.com/chenzhaoyu/p/7831980.html 转载于:https://www.cnblogs.com/x ...

最新文章

  1. Meta 开移动端 AI 生成神器 PyTorch Live,打造人工智能驱动的移动体验
  2. 内核虚拟化技术——LXC初体验
  3. [LeetCode] Remove Duplicates from Sorted Array II
  4. 中国拖拉机市场情况分析与发展趋势预测分析报告2022-2028年版
  5. KDD 2020捷报 | 第四范式斩获KDD Cup全球冠军 AutoML挑战赛圆满落幕
  6. MvcScaffold快速开发实例
  7. 性能指标之速率、带宽、吞吐量
  8. Typora给插图加入图注
  9. ROS错误之RLException: Ubable to launch [xx-1]].
  10. php5.6安装zendopcache加速
  11. Android实现图片滚动控件,含页签功能,让你的应用像淘宝一样炫起来
  12. 杀不死的人狼——我读《人月神话》(三)
  13. 计算机职业生涯规划书素材,职业生涯规划书封面素材
  14. 乌镇、世博、上海游之西、东栅
  15. Autolayout的一点理解
  16. 软件测试技术之iOS 单元测试—逻辑测试
  17. wso2_围绕开放标准改进WSO2 API Manager密钥管理体系结构
  18. mysql创建数据库(详细)
  19. mysql 查看slow query_MySQL慢查询日志(slow log)
  20. 一个Excel的帮助类——ExcelHelper

热门文章

  1. java 中文转gb2312_Java将GB2312编码转化为汉字
  2. K-means算法(知识点梳理)
  3. 常用的linux技巧,Linux Shell常用技巧(十二)-第二部分
  4. win10u盘被写保护怎么解除_如何去掉写保护?tf磁盘被写保护?win10如何去掉写保护?【U盘写保护怎么去掉?】Microsoft Windows...
  5. linux 更改文件格式
  6. js需要删除页面中某个元素
  7. python加减乘除_python加减乘除
  8. python PNG图片显示
  9. 在mac上怎么把png转换成jpg
  10. 嵌入式(单片机方向)工程师如何做好定位和职业规划