224  
查询码:00000317
无法跟踪实体类型'Expert'的实例,因为已经跟踪了具有相同键值的另一个实例
作者: 魏漫漫 于 2020年07月16日 发布在分类 / 人防组 / 人防后端 下,并于 2020年07月16日 编辑
判断数据重复

一、问题描述

1、功能业务介绍:

该接口主要实现,专家数据修改功能,需验证该专家身份证是否重复问题,若重复则提示:该身份证号已存在,若不存在重复的情况,则修改专家信息。

2、代码如下(报错的代码):


 try
            {
                var result = _repository.GetAllList().Where(e => e.IDNumber == input.IDNumber && e.IsDeleted == false && e.Id != input.Id).ToList();
                if (result.Count() > 0)
                {
                    //该身份证号已存在
                    throw new UserFriendlyException("该身份证号已存在!!");
                }
                else
                {
                    return base.Update(input);
                }
            }
            catch (Exception e)
            {
                throw new UserFriendlyException(e.Message);
            }


3、报错提示信息:

 "message": "The instance of entity type 'Expert' 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.",

翻译为:无法跟踪实体类型“Expert”的实例,因为已在跟踪另一个具有相同{'Id'}键值的实例。当给定实体附加一个实例时,请确保只附加一个实体值。考虑使用'DbCOnTestOptionsBuilder.EnableSensitiveCatalogging'以查看冲突的键值。

二、问题解决方式

1、使用Any检查数据是否存在

            try
            {
                var exists = _repository.GetAll().Any(e => e.IDNumber == input.IDNumber && e.IsDeleted == false && e.Id != input.Id);
                if (exists)
                {       //该身份证号已存在
                    throw new UserFriendlyException("该身份证号已存在!!");
                }
                else
                {
                    var updatedEntity = ObjectMapper.Map<Expert>(input);
                    var entity = _repository.UpdateAsync(updatedEntity);
                    return Task.FromResult<DetailExpertDto>(entity.Result.MapTo<DetailExpertDto>());
                }
            }
            catch (Exception e)
            {
                throw new UserFriendlyException(e.Message);
            }


2、使用GetAll().Where判断是否存在


            try
            {
                var exists = _repository.GetAll().Where(e => e.IDNumber == input.IDNumber && e.IsDeleted == false && e.Id != input.Id);
                if (exists.Count() > 0)
                {       //该身份证号已存在
                    throw new UserFriendlyException("该身份证号已存在!!");
                }
                else
                {
                    return base.Update(input);
                }
            }
            catch (Exception e)
            {
                throw new UserFriendlyException(e.Message);
            }

三、总结原因


1、IQueryable<TEntity> GetAll() 与 List<TEntity> GetAllList() 区别

IQueryable和IEnumerable都是延时执行(Deferred Execution)的,而IList是即时执行(Eager Execution)

IQueryable和IEnumerable在每次执行时都必须连接数据库读取,而IList读取一次后,以后各次都不需连接数据库。前两者很容易造成重复读取,性能低下,并且可能引发数据不一致性

IQueryable弊端:当把查询出来的数据,根据指定条件添加到其他表中时,会报连接以打开错误!原因:IQueryable在每次执行时都必须连接数据库读取,所以数据库连接是一直开着的!

以下代码会报错,错误代码数据库连接已经打开无法插入数据:

public IQueryable<Et_ErrorType> ErrorTypeSelect()
{
IQueryable<Et_ErrorType> Br = from B in nContext.Et_ErrorType
select B;
return Br;
}

var  aa=ErrorTypeSelect();

foreach(var kk in aa)

{

if(kk.type=="400")

{

//添加语句

}

}





 推荐知识

 历史版本

修改日期 修改人 备注
2020-07-16 14:47:01[当前版本] 魏漫漫 创建版本

  目录
    知识分享平台 -V 4.8.7 -wcp