EF Core 7中如何在导航属性中使用非跟踪实体?
问题:EF Core 7中导航属性使用非跟踪实体导致SqlException的解决办法
我有一个基于Entity Framework Core 7开发的数据库处理类库,负责将实体返回给客户端代码,客户端会将这些实体赋值给导航属性,示例代码如下:
var newEntity = new SomeEntity { SomeProperty = "blah blah blah", SomeNavProperty = theLibrary.GetEntity() }; theLibrary.Process(newEntity); // 调用DbSet<TEntity>.Add theLibrary.Save(); // 调用DbContext.SaveChanges
原本运行正常,但GetEntity方法返回的是跟踪实体,一旦客户端修改该实体的属性,调用SaveChanges时这些修改会被持久化到数据库,这不符合预期。于是我修改GetEntity让它返回非跟踪实体:
public SomeAnotherEntity GetEntity() { return dbContext.SomeAnotherEntities.AsNoTracking().SingleOrDefault(e => e.Id == 1); }
这一修改导致DbContext的SaveChanges方法抛出SqlException,错误信息如下:
Cannot insert explicit value for identity column in table 'SomeAnotherEntities' when IDENTITY_INSERT is set to OFF.
请问如何在导航属性中使用来自AsNoTracking的非跟踪实体?或者说,怎么修复这个异常?注:在调用DbSet<TEntity>.Add前附加非跟踪关联实体的方法无效。
类库代码
实际的数据库操作类是泛型类,TEntity为处理的实体类型,Process方法代码如下:
public void Process(TEntity entity) { int? id = (int?)typeof(TEntity).GetProperty("Id")?.GetValue(entity); if (id == null) { throw new InvalidOperationException("No Id property"); } if (id == 0) table.Add(entity); else { var tracked = table.Find(id); if (tracked == null) return; foreach (var property in tracked.GetType().GetProperties()) { if (property.Name == "Id") continue; property.SetValue(tracked, property.GetValue(entity)); } } }
table是存储TEntity类型实体的DbSet<TEntity>(已在构造函数中初始化)。Save方法仅调用SaveChanges。
参考用的SomeEntity实体定义:
public class SomeEntity { public int Id { get; set; } public string SomeProperty { get; set; } public SomeAnotherEntity SomeNavProperty { get; set; } }
已尝试方案
我查找过类似问题,有两个相关提问:
- 其中一个有答案,但对当前场景无效。
- 另一个无有效答案,评论区也未提供解决方案,且在提问者补充完整代码前无法进一步解答。
内容的提问来源于stack exchange,提问作者SNBS
相关产品推荐
相关产品推荐

