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. Women forum两周年有感

    今天是个高兴的日子,Women forum两周年庆. 当Nicole上台分享了她当妈妈的经历时,我感动得要哭了,导致轮到我上台演讲的时候,还沉浸在那种情绪中,导致我脱稿演讲了,于是我就超时了,实在是抱 ...

  2. Go | 浅谈包管理模式

    任何一门编程语言都离不开对各种工具包的使用,工具包的管理就显得异常重要了.Go 的包管理方式是逐渐演进的,本文介绍Go语言的两种包管理模式. GOPATH模式引包(不推荐) 在 1.5 版本之前,所有 ...

  3. DRConv:旷视提出区域感知动态卷积,多任务性能提升 | CVPR 2020

    论文提出DRConv,很好地结合了局部共享的思想并且保持平移不变性,包含两个关键结构,从实验结果来看,DRConv符合设计的预期,在多个任务上都有不错的性能提升   来源:晓飞的算法工程笔记 公众号 ...

  4. KingbaseES Json 系列一:Json构造函数

    KingbaseES Json 系列一--Json构造函数(JSON,ROW_TO_JSON,TO_JSON,TO_JSONB) JSON 数据类型是用来存储 JSON(JavaScript Obje ...

  5. 【Java面试题】Mybatis

    五.MyBatis 40)谈谈 MyBatis Mybatis 是一个半自动化的 ORM 框架,它对 jdbc 的操作数据库的过程进行封装,使得开发者只需要专注于 SQL 语句本身,而不用去关心注册驱 ...

  6. 【已解决】linux centos7系统磁盘扩容

    第一步要手动加硬盘(我的操作是在20G的基础上加了30G) [reliable@hadoop102 ~]$ su root密码: 查看当前磁盘挂载情况: [root@hadoop102 reliabl ...

  7. #Dinic,最大权闭合子图#CF1473F Strange Set

    题目 分析 对于这种依赖关系,可以将正权值连源点,负权值连汇点, 然后 \(i\) 向 \(j(j<i)\) 连无穷大的边,注意到如果完全建图空间不够, 考虑记录每个约数最后一次出现的位置,直接 ...

  8. #dp,模型转换,排列组合#AT1983 [AGC001E] BBQ Hard

    题目 有两个长度为\(n\)的序列\(a,b\),需要求 \[\sum_{i=1}^n\sum_{j=i+1}^nC(a_i+b_i+a_j+b_j,a_i+a_j) \] 其中\(n\leq 200 ...

  9. 爱奇艺携手HMS Core,为用户打造更流畅的沉浸式观影体验

    本文分享于HMS Core开发者论坛<[开发者说]爱奇艺携手HMS Core,为用户打造更流畅.更沉浸的观影体验>采访稿整理. 爱奇艺是国内领先的视频播放平台,通过接入HMS Core H ...

  10. HarmonyOS音频开发指导:使用AVPlayer开发音频播放功能

      如何选择音频播放开发方式 在HarmonyOS系统中,多种API都提供了音频播放开发的支持,不同的API适用于不同音频数据格式.音频资源来源.音频使用场景,甚至是不同开发语言.因此,选择合适的音频 ...