The instance of entity type 'Model' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.

新增数据到数据库后再在同一个方法或请求更新某些字段报的错误,大概的意思就是=>

无法跟踪实体类型“Model”的实例,因为已经在跟踪具有相同键值{'Id'}的另一个实例。在附加现有实体时,请确保只附加一个具有给定键值的实体实例。考虑使用' dbcontexttoptionsbuilder。EnableSensitiveDataLogging'查看冲突的键值。

我的做法是既然同一个链接,那么我就重新弄一个连接出来,因为我这efcore组件封装了,取context有点麻烦。所以选择别的办法。

源代码如下,报错的地方就是@2这里的更新引发错误:

 [HttpPost]
public async Task SaveData(PushMessageUpdateRequest data)
{
if (data == null)
throw new BusException($"{nameof(PushMessageUpdateRequest)} is null", ErrorCodeDefine.ParameterIsNull);
if (data.Id.IsNullOrEmpty())
{
InitEntity(data);
foreach (var content in data.Contents)
{
InitEntity(content);
}
await _pushMessageBusiness.AddDataAsync(data);
var res = await _soptBusiness.FirstOrDefault(x => x.BusinessCode == "tttt").GetCustomerPushInfo();
var groups = res.Where(x => x.Value != null).GroupBy(x => x.Value).ToDictionary(x => x.Key, y => y.Select(x => x.Key).ToList());
List<bool> pushedFlag = new List<bool> { };
foreach (var item in groups)
{
var pushContent = data.Contents.Where(x => x.Lang == item.Key.ToLower()).FirstOrDefault();
if (pushContent != null && pushContent.Content.IsNotNullOrEmpty())
{
if (data.PushTime == null)
{
var result = await _pushClient.SendPush(new Klickl.Push.Sdk.Model.SendPushRequest
{
Type = Klickl.Push.Sdk.Model.PushType.Google,
Ids = item.Value,
NoticeContent = pushContent?.Content,
Title = pushContent?.Title,
IsApnsProduction = false
});
pushedFlag.Add(result);
}
else
{
JobHelper.SetDelayJob(async () =>
{
var result = await _pushClient.SendPush(new Klickl.Push.Sdk.Model.SendPushRequest
{
Type = Klickl.Push.Sdk.Model.PushType.Google,
Ids = item.Value,
NoticeContent = pushContent?.Content,
Title = pushContent?.Title,
IsApnsProduction = false
});
pushedFlag.Add(result);
}, data.PushTime.Value.Subtract(DateTime.Now));
} }
} data.SuccessCount= pushedFlag.Where(x=>x==true).Count(); //@1
data.PushCount = groups.Count;
await _pushMessageBusiness.UpdateDataAsync(data); //@2
}
else
{
await _pushMessageBusiness.UpdateDataAsync(data);
}
}

首先想的是_pushMessageBusiness这个business重新构造一个,像这样@3新增的business,@4就是为了报错加上去的。测试发现还是报一样的错误。

  private readonly IPushMessageBusiness _pushMessageBusiness;  //@3
private readonly PushClient _pushClient;
private readonly IEnumerable<ISpotBusiness> _soptBusiness;
private readonly IAutoPushMessageBusiness _autoPushMessageBusiness;
private record SaveDataChangeEventArgs(string Id, int SucessCount, int PushCount);
private EventHandler<SaveDataChangeEventArgs> SaveDataChangeEventEventHandler; private readonly IPushMessageBusiness _updataPushMessageBusiness; @4
private IServiceScopeFactory _scopeFactory;

因为_pushMessageBusiness里面有idbaccessor,及数据库的底层链接,所以上面注入idbaccessor是没问题,可以把bug解决掉,但是这样取原始远不如获取business安全和稳定。

解决办法如下:

                data.SuccessCount= pushedFlag.Where(x=>x==true).Count();
data.PushCount = groups.Count;
await _pushMessageBusiness.UpdateDataAsync(data);

上面代码最好独立出来,我通过事件来更新。

   if (groups.Count > 0 && SaveDataChangeEventEventHandler != null)
SaveDataChangeEventEventHandler(this, new SaveDataChangeEventArgs(data.Id, pushedFlag.Where(x => x == true).Count(), groups.Count));

事件放到构造函数,主要是新注入了一个scope工厂,这个也是关键代码,生成了的business和原来是不一样的。代码如下:

  public PushMessageController(IPushMessageBusiness pushMessageBusiness,
IPushClientFactory factory,
IEnumerable<ISpotBusiness> soptBusiness, IAutoPushMessageBusiness autoPushMessageBusiness,
IServiceScopeFactory scopeFactory)
{
_pushMessageBusiness = pushMessageBusiness;
_pushClient = factory.Create("ttttt");
_soptBusiness = soptBusiness;
_autoPushMessageBusiness = autoPushMessageBusiness;
_scopeFactory = scopeFactory;
SaveDataChangeEventEventHandler += (obj, args) =>
{
AsyncHelper.RunSync(async () =>
{
using(var scope = _scopeFactory.CreateAsyncScope())
{
var _bus = scope.ServiceProvider.GetRequiredService<IPushMessageBusiness>();
var entity = await _bus.GetEntityAsync(x => x.Id.Equals(args.Id));
if (entity == null) { return; }
entity.SuccessCount = args.SucessCount;
entity.PushCount = args.PushCount;
await _bus.UpdateAsync(entity);
} }); }; } private readonly IPushMessageBusiness _pushMessageBusiness;
private readonly PushClient _pushClient;
private readonly IEnumerable<ISpotBusiness> _soptBusiness;
private readonly IAutoPushMessageBusiness _autoPushMessageBusiness;
private record SaveDataChangeEventArgs(string Id, int SucessCount, int PushCount);
private EventHandler<SaveDataChangeEventArgs> SaveDataChangeEventEventHandler; private IServiceScopeFactory _scopeFactory;
 public static class AsyncHelper
{
private static readonly TaskFactory _myTaskFactory =
new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); /// <summary>
/// 同步执行
/// </summary>
/// <param name="func">任务</param>
public static void RunSync(Func<Task> func)
{
_myTaskFactory.StartNew(func).Unwrap().ConfigureAwait(false).GetAwaiter().GetResult();
} /// <summary>
/// 同步执行
/// </summary>
/// <typeparam name="TResult">返回类型</typeparam>
/// <param name="func">任务</param>
/// <returns></returns>
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return _myTaskFactory.StartNew(func).Unwrap().ConfigureAwait(false).GetAwaiter().GetResult();
}
}

The instance of entity type 'Model' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked.的更多相关文章

  1. The instance of entity type 'xxxx' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked.

    一.问题描述 问题:The instance of entity type 'xxxx' cannot be tracked because another instance with the sam ...

  2. The instance of entity type 'Menu' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked.

    这里记录一个在使用.net core中ef core执行数据库操作时遇到的问题: 我在代码中使用DbContext下的Update方法准备将更改后的数据像这样步到数据库: _context.Menus ...

  3. EF 更新实体 The instance of entity type 'BabyEvent' cannot be tracked because another instance

    加上AsNoTracking. 人不能两次踏入同一条河. 我 就踏入了.o(╥﹏╥)o

  4. The instance of entity type 'manager' cannot be tracked because another instance with the same key value for {'id'} is already being tracked. When attaching existing entities, ensure that only one ent

    最近在用ASP.NET CORE时遇到一些问题,现记录下: 出现上述错误,即在更新实体数据时出现的错误 services.AddDbContext<StoreContext>(c => ...

  5. The entity type XXX is not part of the model for the current context.

    今天遇到了一个奇葩问题,虽然解决了,但还是一脸懵,先附赠一下别人的解决方案:https://www.cnblogs.com/zwjaaron/archive/2012/06/08/2541430.ht ...

  6. Entity Framework的核心 – EDM(Entity Data Model) 一

    http://blog.csdn.net/wangyongxia921/article/details/42061695 一.EnityFramework EnityFramework的全程是ADO. ...

  7. EF,ADO.NET Entity Data Model简要的笔记

    1. 新建一个项目,添加一个ADO.NET Entity Data Model的文件,此文件会生成所有的数据对象模型,如果是用vs2012生的话,在.Designer.cs里会出现“// Defaul ...

  8. Create Entity Data Model

    http://www.entityframeworktutorial.net/EntityFramework5/create-dbcontext-in-entity-framework5.aspx 官 ...

  9. [转] EF cannot be tracked because another instance of this type with the same key is already being tracked

    本文转自:http://stackoverflow.com/questions/6033638/an-object-with-the-same-key-already-exists-in-the-ob ...

  10. Entity Framework Tutorial Basics(5):Create Entity Data Model

    Create Entity Data Model: Here, we are going to create an Entity Data Model (EDM) for SchoolDB datab ...

随机推荐

  1. 用免费GPU部署自己的stable-diffusion项目(AI生成图片)

    2021年时出现了 openAI 的 DALL,但是不开源.2022年一开年,DALL-E 2发布,依然不开源.同年7月,Google 公布其 Text-to-Image 模型 Imagen,并且几乎 ...

  2. Python 批量合并csv文件

    一.批量合并csv文件<方法1> import pandas as pd import glob import os # 获取所有CSV文件的路径 file_paths = glob.gl ...

  3. axios中设置了response:blol后,如何处理json对象

    axios中文件下载 上传文件后台校验,若失败则下载文件 let loading = this.$common.loading("正在上传"); let form = new Fo ...

  4. 一文讲透Java核心技术之高可扩展利器SPI

    大家好,我是冰河~~ SPI的概念 JAVA SPI = 基于接口的编程+策略模式+配置文件 的动态加载机制 SPI的使用场景 Java是一种面向对象语言,虽然Java8开始支持函数式编程和Strea ...

  5. Dynamic ReLU:微软推出提点神器,可能是最好的ReLU改进 | ECCV 2020

    论文提出了动态ReLU,能够根据输入动态地调整对应的分段激活函数,与ReLU及其变种对比,仅需额外的少量计算即可带来大幅的性能提升,能无缝嵌入到当前的主流模型中   来源:晓飞的算法工程笔记 公众号 ...

  6. HTML实现发送接收串口和TCP数据

    前提 请安装通讯调试工具,所有的网页必须运行在本工具上,在其他浏览器直接打开是不行的. 效果显示 在网页上右键打开,选择其他应用 2.在其他应用中找到通讯调试工具 如果没有这一项,点更多,在计算机中查 ...

  7. 讲讲百度地图API遇到的坑,石锤百度官方代码的错,解决SN校验失败

    这两天在做一个项目,用到了百度地图API,根据坐标获取具体位置,总结一下遇到的几个坑 本文基于最新的V3接口,网上好多要么是V2,要么根据地址获取坐标,本文是唯一一个最新的3,根据坐标获取位置的完整说 ...

  8. 基于spring-boot、grpc、zookeeper的分布式微服务架构

    总览: 开源.高性能.多语言.跨平台.易扩展rpc框架 . Protocol Buffers 使用 默认使用 protocol buffers,Google 开源的成熟序列化机制: 文件格式:.pro ...

  9. .editorConfig常用设置

    # http://editorconfig.org root = true [*] # 表示所有文件适用charset = utf-8 # 设置文件字符集为 utf-8indent_style = s ...

  10. #SPFA#洛谷 4042 [AHOI2014/JSOI2014] 骑士游戏

    题目 分析 如果我想普通攻击1,那么必须干掉所有产生的其它怪兽,这不由得可以用一个不等式来表示, \(普攻+\sum need<法攻\) 但是所需要消灭的怪兽同样可以这样进行,所以它可能具有后效 ...