EF Core 5多对多关系插入ItemAttributeCluster触发IDENTITY_INSERT错误如何解决
问题原因
你调用_context.ItemAttributeClusters.Add(itemAttributeCluster)时,传入的itemAttributeCluster对象关联的itemAttributes集合里的所有ItemAttribute实例,在当前EF上下文中都处于游离态,EF会默认将这些游离态对象标记为Added状态,级联执行插入操作。而你传入的ItemAttribute已经带了自增主键ItemAttributeId的值,SQL Server默认不允许手动插入自增列的值,就抛出了你遇到的错误。
解决方法
方案1:将关联的ItemAttribute标记为已存在
在插入ItemAttributeCluster之前,手动把所有关联的ItemAttribute附加到上下文,告诉EF这些是已经存在的实体,不需要新增:
[HttpPost] public async Task<IActionResult> Post(ItemAttributeCluster itemAttributeCluster) { // 附加所有关联的ItemAttribute,标记为未修改状态,EF不会尝试插入 foreach (var attr in itemAttributeCluster.itemAttributes) { _context.ItemAttributes.Attach(attr); } _context.ItemAttributeClusters.Add(itemAttributeCluster); await _context.SaveChangesAsync(); return Ok(itemAttributeCluster); }
这个方案改造成本最低,直接修改现有接口即可,注意要保证传入的ItemAttributeId是数据库中真实存在的,否则会触发外键约束报错。
方案2:从数据库查询关联的ItemAttribute
如果需要做合法性校验,可以先定义入参DTO只接收关联的ItemAttributeId列表,再从数据库取出对应的实体赋值给集群对象,这些取出的实体本身就处于被上下文跟踪的状态,不会被当成新实体插入:
[HttpPost] public async Task<IActionResult> Post(ItemAttributeClusterCreateDto dto) { var cluster = new ItemAttributeCluster { Titel = dto.Titel, IsMultiChoice = dto.IsMultiChoice, itemAttributes = await _context.ItemAttributes .Where(a => dto.ItemAttributeIds.Contains(a.ItemAttributeId)) .ToListAsync() }; _context.ItemAttributeClusters.Add(cluster); await _context.SaveChangesAsync(); return Ok(cluster); }
这个方案更严谨,自动过滤了不存在的ItemAttributeId,适合生产环境使用。
内容的提问来源于stack exchange,提问作者T0bi
相关产品推荐
相关产品推荐

