The instance of entity type 'Model' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked.
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.的更多相关文章
- 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 ...
- 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 ...
- EF 更新实体 The instance of entity type 'BabyEvent' cannot be tracked because another instance
加上AsNoTracking. 人不能两次踏入同一条河. 我 就踏入了.o(╥﹏╥)o
- 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 => ...
- 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 ...
- Entity Framework的核心 – EDM(Entity Data Model) 一
http://blog.csdn.net/wangyongxia921/article/details/42061695 一.EnityFramework EnityFramework的全程是ADO. ...
- EF,ADO.NET Entity Data Model简要的笔记
1. 新建一个项目,添加一个ADO.NET Entity Data Model的文件,此文件会生成所有的数据对象模型,如果是用vs2012生的话,在.Designer.cs里会出现“// Defaul ...
- Create Entity Data Model
http://www.entityframeworktutorial.net/EntityFramework5/create-dbcontext-in-entity-framework5.aspx 官 ...
- [转] 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 ...
- 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 ...
随机推荐
- mysql mysqldump 命令导出
1.导出指定表的数据 mysqldump -t database -u user -p --table_name1 table_name2 table_name3 >C:\db_script. ...
- Postman模拟向Eureka注册服务
1.官方地址:https://github.com/Netflix/eureka/wiki/Eureka-REST-operations 2.自己搭建一个 Eureka服务运行起来. 3.打开Post ...
- KingbaseES V8R6备份恢复案例之---备份crond计划任务的调整
案例说明: 在KingbaseES V8R6数据库通常备份建立的crond任务,默认由root用户建立,写入到/etc/cron.d/KINGBASECRON文件中,在有的生产环境限制了普通用户使用r ...
- Collation 差异导致 KingbaseES 与 Oracle 查询结果不同
问题引入 前端提了个问题,说是KingbaseES 返回的结果与 Oracle 返回的结果不一样.具体问题如下: oracle 执行结果:oracle 有结果返回. SQL> create ta ...
- Kingbase Create Type 语句使用
Kingbase create type类型创建语句 说明: KingbaseES 数据库中,可以通过CREATE TYPE语句定义一种新的数据类型. 有八种形式的CREATE TYPE.它们分别创建 ...
- Android开发 活动activity
一.关于Activity 关于Activity必须要了解的内容有:Activity的生命周期.android任务栈.Activity启动模式.scheme跳转协议. 1.1 什么是Activity ...
- 基于spring-boot、grpc、zookeeper的分布式微服务架构
总览: 开源.高性能.多语言.跨平台.易扩展rpc框架 . Protocol Buffers 使用 默认使用 protocol buffers,Google 开源的成熟序列化机制: 文件格式:.pro ...
- Go 项目依赖注入wire工具最佳实践介绍与使用
目录 一.引入 二.控制反转与依赖注入 三.为什么需要依赖注入工具 3.1 示例 3.2 依赖注入写法与非依赖注入写法 四.wire 工具介绍与安装 4.1 wire 基本介绍 4.2 安装 五.Wi ...
- Sqlite数据库联合查询及表复制等详述
外键:一般在两个表之间要建立关联时候,创建一个列创建 为外键(UserInfos-DeptId),它在另一个表必须是主键(DeptInfos-DeptId) 元素约束:主键约束:主要区别内容相同的行, ...
- 【FAQ】运动健康服务云侧数据常见问题及解答
目录 Q1:v2接口相比于v1接口传参及返回的数据格式有变化吗?是否可以直接将v1接口改成v2接口? Q2:如何获取采集健康数据的穿戴设备信息? Q3:如何处理非华为手机产生的步数调用采样明细接口查询 ...