【问题标题】:.Net Core error System.InvalidOperationException: The instance of entity type is already being tracked.Net Core错误System.InvalidOperationException:实体类型的实例已经被跟踪
【发布时间】:2020-06-29 09:29:24
【问题描述】:

我正在开发一个带有 Angular 和 .Net Core 的 web api。 我真的是 .Net 的新手,但是当我尝试在此端点更新进程时,我收到此错误: “执行请求时发生未处理的异常。System.InvalidOperationException:无法跟踪实体类型'EtapaEmpleado'的实例,因为已经在跟踪另一个具有相同键值的实例 {'IdEtapa', 'IdEmpleado'}”。

这是我的代码:

        [HttpPut("{id}")]
        public async Task<IActionResult> PutEtapa([FromRoute] int id, [FromBody] EditEtapaDto editEtapaDto)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (id != editEtapaDto.IdEtapa)
            {
                return BadRequest();
            }

            
            var preEtapa = _mapper.Map<Etapa>(editEtapaDto);
            //Prueba
            foreach(var a in preEtapa.EtapaEmpleado)
            {
                var preEtapaEmpleado=_mapper.Map<EtapaEmpleado>(a);
                if(_context.EtapaEmpleado.Where(z=>z.IdEmpleado==preEtapaEmpleado.IdEmpleado).Count()>0 && _context.EtapaEmpleado.Where(x=>x.IdEtapa==preEtapaEmpleado.IdEtapa).Count()>0)
                {
                    var tiempoAntes=_context.EtapaEmpleado.FirstOrDefault(z=>z.IdEmpleado==preEtapaEmpleado.IdEmpleado && z.IdEtapa==preEtapaEmpleado.IdEtapa);
                    var condicion=String.IsNullOrEmpty(tiempoAntes.TiempoParc);
                    if(condicion==false)
                    {
                        string[] arrTAntesStr=tiempoAntes.TiempoParc.Split(':');
                        string[] arrTDespuesStr=preEtapaEmpleado.TiempoParc.Split(':');
                        int[] tiempoAntesArrInt= Array.ConvertAll(arrTAntesStr,Int32.Parse);
                        int[] tiempoDespuesArrInt=Array.ConvertAll(arrTDespuesStr,Int32.Parse);
                        int[] tiempoIntFinal={0,0,0,0};
                        int meLlevoUno=0;
                        string tiempoStringFinal=null;
                        
                        for(int i=3;i>-1;i--)
                        {
                            switch(i){
                                default:
                                    
                                 tiempoIntFinal[i]=tiempoAntesArrInt[i]+tiempoDespuesArrInt[i]+meLlevoUno;
                                    meLlevoUno=tiempoIntFinal[i]/60;
                                    tiempoIntFinal[i]=tiempoIntFinal[i]%60;
                                    break;
                                case 0:
                                        tiempoIntFinal[i]=tiempoAntesArrInt[i]+tiempoDespuesArrInt[i]+meLlevoUno;
                                        break;
                                case 1:
                                    tiempoIntFinal[i]=tiempoAntesArrInt[i]+tiempoDespuesArrInt[i]+meLlevoUno;
                                    meLlevoUno=tiempoIntFinal[i]/24;
                                    tiempoIntFinal[i]=tiempoIntFinal[i]%24;
                                    break;
                    
                            }
                        }

                        
                        var builder = new StringBuilder();
                        for(int j=0;j<tiempoIntFinal.Length;j++)
                        {
                            if(tiempoIntFinal[j]<10)
                            {
                                builder.Append("0");
                            }
                            builder.Append(tiempoIntFinal[j]);
                            if(j!=3)
                            {
                                builder.Append(":");    
                            }
                            
                            tiempoStringFinal=builder.ToString();
                        }   

                        preEtapaEmpleado.TiempoParc=tiempoStringFinal;

                    }
                    

                    try{
                        
                        //preEtapaEmpleado.TiempoParc=preEtapa.TiempoParc;
                        _repo2.Update(preEtapaEmpleado);
                           

                    }
                    catch(DbUpdateConcurrencyException){
                        throw;
                    }
                }
                else{
                    try{

                        _repo2.Add(preEtapaEmpleado);
                    }
                    catch(DbUpdateConcurrencyException)
                    {
                        throw;
                    }
                }

                await _repo2.SaveAsync(preEtapaEmpleado);
            }

             _repo.Update(preEtapa);
            await _repo.SaveAsync(preEtapa);
            return StatusCode(201,preEtapa);


这是我的 IDataRepository:

namespace Foha.Repositories
{
    public interface IDataRepository<T> where T : class
    {
        void Add(T entity);
        void Update(T entity);
        void Delete(T entity);
        Task<T> SaveAsync(T entity);
    }
}

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    当你打电话时

    var tiempoAntes=_context.EtapaEmpleado.FirstOrDefault(z=&gt;z.IdEmpleado==preEtapaEmpleado.IdEmpleado &amp;&amp; z.IdEtapa==preEtapaEmpleado.IdEtapa);

    它开始在_context 中跟踪该实体。我假设_repo2 使用相同的_context

    如果是这样,那么当您尝试添加具有相同 ID 的对象 _repo2.Update(preEtapaEmpleado); 的副本时,上下文会将其识别为重复项并引发错误。

    这篇文章可能会有所帮助

    https://docs.microsoft.com/en-us/ef/core/querying/tracking

    【讨论】:

    • 太棒了! .实际上,_repo _repo2 使用相同的_context... 那篇文章对我有用,并帮助我解决了这个问题,将AsNoTracking() 方法添加到tiempoAntes。非常感谢!
    猜你喜欢
    • 2021-05-04
    • 1970-01-01
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    • 1970-01-01
    • 2022-01-26
    相关资源
    最近更新 更多