如何在将记录添加到DbSet前判断其是否为新记录?适配手动设置主键场景
解决方案
你现在的逻辑问题在于默认假设主键是自增生成,仅靠主键是否为默认值判断新增场景,对提前手动赋值主键的场景自然不适用。可以直接使用EF内置的逻辑处理,两种常用实现方案如下:
方案1:使用内置AddOrUpdate方法(改动最小)
EF 自带的AddOrUpdate方法已经封装了完整的新增/更新判断逻辑,兼容自增主键、手动赋值主键等所有场景,直接替换原有判断即可:
public void Prepare<T>(T model) where T : class { var key = ReflectionHelper.GetAttribute<T, KeyAttribute>(); if(null == key) { return; } SetContext<T>(); DbManager.Context.Set<T>().AddOrUpdate(model); }
注意:EF6 中该方法位于
System.Data.Entity.Migrations命名空间,EF Core 中位于Microsoft.EntityFrameworkCore命名空间,按需引用对应命名空间即可。
方案2:自定义判断逻辑(灵活可控)
如果需要自定义处理逻辑,不想依赖内置方法,可以通过主键查询判断记录是否存在,再决定操作类型,优先查上下文本地缓存避免不必要的数据库请求:
public void Prepare<T>(T model) where T : class { var keyProperty = ReflectionHelper.GetAttribute<T, KeyAttribute>(); if(null == keyProperty) { return; } SetContext<T>(); var dbSet = DbManager.Context.Set<T>(); var keyValue = keyProperty.GetValue(model); // 优先查本地追踪缓存,无匹配再查数据库 var existingEntity = dbSet.Local.FirstOrDefault(e => keyProperty.GetValue(e).Equals(keyValue)) ?? dbSet.Find(keyValue); if (existingEntity == null) { // 无匹配记录,执行新增 dbSet.Add(model); } else { // 已有匹配记录,更新字段值 DbManager.Context.Entry(existingEntity).CurrentValues.SetValues(model); } }
如果你的上下文是短生命周期(比如每次请求新建实例),本地缓存基本无数据,可以省略本地查询步骤,直接调用Find方法查询即可。
内容的提问来源于stack exchange,提问作者Damian
相关产品推荐
相关产品推荐

