EF Core添加新Entity生成负Id 数据库Id值正常如何排查解决?
EF Core添加实体后返回Id为负值但数据库自增Id正常问题
我在尝试添加新的Container实体时遇到问题:添加实体后,返回的数据集里显示的Id为负值,但我的SQL数据库中刚插入的Container的Id是正确的下一个自增值。
我查阅过相关资料,类似问题多出现在添加实体前先执行Update操作的场景,但我没有找到首次添加实体时出现该错误的相关说明。
我仅实例化了一个新的Container对象,将其添加到ProductContext的Containers DbSet中,相关代码如下:
public class ProductService : IProductService { private readonly IProductContext _productContext; public ProductService(IProductContext productContext) { _productContext = productContext; } public Container CreateContainer(Container container, int currentUserId) { _productContext.Containers.Add(container); _productContext.SaveChangesAsync(); return container; } }
单步调试时可以看到,初始状态下Id为0:
执行保存操作后,container的Id变为-2147482645:
但查询数据库可以看到对应的记录Id为正确的下一个自增值,该值没有同步更新到实体对象上,实体一直保留-2147482645的负Id值。
实体定义
我的Container实体定义如下:
public class Container : BaseEntity { public Container() { this.ChildContainers = new HashSet<Container>(); this.InventoryItems = new HashSet<InventoryItem>(); } public ICollection<Container> ChildContainers { get; set; } public ICollection<InventoryItem> InventoryItems { get; set; } public Location Location { get; set; } public int? LocationId { get; set; } public string Name { get; set; } [ForeignKey("ParentContainerId")] public Container ParentContainer { get; set; } public int? ParentContainerId { get; set; } }
继承的BaseEntity类定义如下:
public abstract class BaseEntity { [Key] public virtual int Id { get; set; } [DefaultValue(false)] public virtual bool IsDeleted { get; set; } protected virtual object Actual => this; public override bool Equals(object obj) { if (!(obj is BaseEntity other)) return false; if (ReferenceEquals(this, other)) return true; if (Actual.GetType() != other.Actual.GetType()) return false; if (Id == 0 || other.Id == 0) return false; return Id == other.Id; } public static bool operator ==(BaseEntity a, BaseEntity b) { if (a is null && b is null) return true; if (a is null || b is null) return false; return a.Equals(b); } public static bool operator !=(BaseEntity a, BaseEntity b) { return !(a == b); } public override int GetHashCode() { return (Actual.GetType().ToString() + Id).GetHashCode(); } public DateTime CreatedDate { get; set; } public DateTime UpdatedDate { get; set; } }
SaveChangesAsync重写实现
我重写的SaveChangesAsync方法实现如下:我认为这部分不会影响Id生成,因为Id在进入该方法前就已经被赋值了。
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) { var entries = ChangeTracker .Entries() .Where(e => e.Entity is BaseEntity && ( e.State == EntityState.Added || e.State == EntityState.Modified)); foreach (var entityEntry in entries) { ((BaseEntity)entityEntry.Entity).UpdatedDate = DateTime.Now; if (entityEntry.State == EntityState.Added) { ((BaseEntity)entityEntry.Entity).CreatedDate = DateTime.Now; } } return await base.SaveChangesAsync(); }
编辑1:同步调用SaveChanges相关说明
有观点认为我同步调用异步SaveChangesAsync方法可能引发该问题,但我认为这不是根本原因,因为Id在Add方法执行阶段就已经被修改了。
内容的提问来源于stack exchange,提问作者Chris Hobbs
相关产品推荐
相关产品推荐

