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. Liunx-LVM创建与扩容

    LVM是 Logical Volume Manager(逻辑卷管理)的简写,它是Linux环境下对磁盘分区进行管理的一种机制,它由Heinz Mauelshagen在Linux 2.4内核上实现,最新 ...

  2. flink scala 从Oracle同步数据到MySql

    pom <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> ...

  3. Oracle与Java JDBC数据类型对照

    Oracle Database JDBC开发人员指南和参考 SQL Data Types JDBC Type Codes Standard Java Types Oracle Extension Ja ...

  4. 用cmd检查端口关闭命令

    1.进入cmd 2.netstat -o -n -a | findstr :8080 TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 3116 3.taskkill /F / ...

  5. KingbaseES V8R6 fillfactor 对于表的影响

    前言 fillfactor 表的填充因子是一个介于 10 和 100 之间的百分数.100是默认值.如果指定了较小的填充因子,INSERT操作仅按照填充因子指定的百分率填充表页.每个页上的剩余空间将用 ...

  6. KingbaseES V8R6 运维案例 --ksql访问动态库问题

    KingbaseES V8R6数据库运维案例之---ksql访问动态库问题 案例说明: CentOS环境下,在安装和初始化数据库实例后,启动数据库服务,通过ksql连接访问时出现以下故障: 经检查,是 ...

  7. Spring框架之控制反转IoC(Inversion of Control)的理解

    简单理解: 控制反转就是将代码的调用权(控制权)从调用方转移给被调用方(服务提供方). 解释一下: 如果我们需要创建某个类,就需要程序员去修改代码,然后才可以得到想要的类.反转的意思就是不需要程序员去 ...

  8. 6 JavaScript条件判断

    6 条件判断 除了HTML以外. 几乎所有的编程语言都有条件判断的功能. 比如, python, 我们用if语句来做条件判断. 到了javascript中也是一样的, 也使用javascript来做条 ...

  9. 成长计划知识赋能 | 第十期:DAYU200开发入门秒Get

      2021年12月,OpenAtom OpenHarmony(以下简称"OpenHarmony")开源开发者成长计划开启了第一节OpenHarmony知识赋能直播课程,给广大开发 ...

  10. DevEco Studio 3.1 Beta1版本发布——新增六大关键特性,开发更高效

      智能代码编辑.端云一体化开发.低代码开发个性化-- 六大新增关键特性,开发更高效,体验更觉妙! 立即点击链接下载,做DevEco Studio 3.1 Beta1版本尝鲜者! 下载链接:HUAWE ...