错误-相同类型的另一个实体已经具有相同的主键值(.NET)

问题描述 投票:0回答:0

下午好,

我有一个错误,我想你可以帮助我。

  • 错误
System.InvalidOperationException
HResult=0x80131509
Message=Attaching an entity of type 'SGI2DataAccess.Models.ProjectForecast' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
Source=EntityFramework
StackTrace:
at System.Data.Entity.Core.Objects.ObjectContext.VerifyRootForAdd(Boolean doAttach, String entitySetName, IEntityWrapper wrappedEntity, EntityEntry existingEntry, EntitySet& entitySet, Boolean& isNoOperation)
at System.Data.Entity.Core.Objects.ObjectContext.AttachTo(String entitySetName, Object entity)
at System.Data.Entity.Internal.Linq.InternalSet`1.<>c__DisplayClassa.<Attach>b__9()
at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
at System.Data.Entity.Internal.Linq.InternalSet`1.Attach(Object entity)
at System.Data.Entity.DbSet`1.Attach(TEntity entity)
at SGI2.Data.Infrastructure.RepositoryBase`1.Update(T entity) in C:\work\sgi\SGI2.Data\Infrastructure\RepositoryBase.cs:line 41
at SGI2.Service.Services.Projects.ForecastProject.UpdateForecast(List`1 forecasts, ProjetoVM Projeto) in C:\work\sgi\SGI2.Service\Services\Projects\ForecastProject.cs:line 79
at SGI2.Service.ProjetosService.UpdateProjeto(ProjetoEditVM VM, Int32 userId, String userNomeConhecido) in C:\work\sgi\SGI2.Service\Services\Projects\ProjetosService.cs:line 1212
at SGI2.Controllers.ProjetosController.Edit(ProjetoEditVM VM, String Command) in C:\work\sgi\SGI2\SGI2\Controllers\Projeto\ProjetosController.cs:line 312
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f()
  • 代码 对象:\sgi2\SGI2\Controllers\Projeto\ProjetosController.cs
(...)
// Interface
private readonly IProjetosService _service;
(...)

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(ProjetoEditVM VM, string Command)
    {
        #region PERMISSOES
        if (!ClaimsAuthorization.CheckAccess("generic-editprojetos", VM.Projeto.Id.ToString(), VM.Projeto.EstadoId.ToString()))
            return new HttpStatusCodeResult(HttpStatusCode.Forbidden);

        // Completed projects should never be able to be edited
        if (_service.GetProjeto(VM.Projeto.Id).EstadoId == 2)
            return new HttpStatusCodeResult(HttpStatusCode.Forbidden);

        #endregion
        else if (ModelState.IsValid)
        {
            if (VM.Projeto.EstadoId == 2 && (VM.Projeto.TipoId == 8 || VM.Projeto.TipoId == 9) && !_service.GetAllProjetosPPRInfo(x => x.ProjetoId == VM.Projeto.Id && x.IsTheLast).Any())
            {
                return RedirectToAction("Edit", new { Id = VM.Projeto.Id, param = "CloseProjectLastPPRInfoError" });
            }


            // Se vem do botão "Refresh Forecast", atualizar valores, antes de submeter com valores desatualizados
            if (Command == "RefreshForecastButton")
            {
                _service.UpdateProjetoRF(VM, UserId, UserNomeConhecido); // ok
                RefreshForecastButton(VM, Command, UserId, UserNomeConhecido);
                _service.UpdateProjeto(VM, UserId, UserNomeConhecido); // NOT ok
            }
            (...) 
        }  (...) 

    }
(...)

对象:\sgi\SGI2.Service\Services\Projects\ProjetosService.cs

public void UpdateProjeto(ProjetoEditVM VM, int userId, string userNomeConhecido)
{
    //Atualiza projeto

    var dbObj = projetosRepository.GetById(VM.Projeto.Id);
    (...)
    new ForecastProject(projectForecastRepository, projetoPPRInfoRepository).UpdateForecast(VM.Forecasts, VM.Projeto);
    (...)
    unitOfWork.Commit();

}

对象:\sgi\SGI2.Service\Services\Projects\ForecastProject.cs

namespace SGI2.Service.Services.Projects
{ 
    //Tenho de criar uma interface e remover a dependecia dos repositórios
    public class ForecastProject
    {  
       
        private readonly IProjectForecastRepository projectForecastRepository;
        private readonly IProjetoPPRInfoRepository projetoPPRInfoRepository;
        private readonly IForecastDomain Iforecast = new ForecastDomain();


        public ForecastProject(IProjectForecastRepository projectForecastRepository, IProjetoPPRInfoRepository projetoPPRInfoRepository)
        {
            this.projectForecastRepository = projectForecastRepository;
            this.projetoPPRInfoRepository = projetoPPRInfoRepository;
        }
        (...)
        
        public void UpdateForecast(List<ProjectForecastEditVM> forecasts, ProjetoVM Projeto)
        {
            // 1º Caso não exista linhas
            if (forecasts == null || forecasts.Count() == 0)
            {
                foreach (var item in Iforecast.InitialLinesForecast(Projeto))
                {
                    projectForecastRepository.Add(item);
                }
            }

            // 2º caso a data de fim do projeto aumente
            else if (Projeto.RealEndDate > forecasts.LastOrDefault().EndDate)
            {
                foreach (var item in Iforecast.ChangeRealEndDateForecast(Projeto,forecasts.LastOrDefault().EndDate))
                {
                    projectForecastRepository.Add(item);
                }
            }

            else
            {
                List<ProjectForecast> Forecasts = new List<ProjectForecast>();
                foreach (var i in forecasts)
                {
                    //Está assim pois a data fim pode mudar e deixar de ser o ultimo dia do mês
                    DateTime EndDate = new DateTime(i.EndDate.Year, i.EndDate.Month, DateTime.DaysInMonth(i.EndDate.Year, i.EndDate.Month));
                    //Ultimo dia do mês do projeto
                    DateTime LastDateofProject = new DateTime(Projeto.RealEndDate.Value.Year, Projeto.RealEndDate.Value.Month, DateTime.DaysInMonth(Projeto.RealEndDate.Value.Year, Projeto.RealEndDate.Value.Month));

                    if (EndDate > LastDateofProject && i.CanWrite == true)
                    {
                        projectForecastRepository.Delete(projectForecastRepository.GetById(i.Id));
                    }
                    else
                    {
                        Forecasts.Add(UpdateForecastForecastFactory(Projeto, i));
                    }
                }

                foreach (var item in Forecasts)
                {
                    projectForecastRepository.Update(item); ! The error is thrown here !
                }
            }
        }
        
    }
}

对象:\SGI2.Data\Infrastructure\IRepository.cs

using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace SGI2.Data.Infrastructure
{
    public interface IRepository<T> where T : class
    {
        // Marks an entity as new
        void Add(T entity);
        // Marks an entity as modified
        void Update(T entity);
        // Marks an entity to be removed
        void Delete(T entity);
        void Delete(Expression<Func<T, bool>> where);
        // Get an entity by int id
        T GetById(int id);
        // Get an entity using delegate
        T Get(Expression<Func<T, bool>> where);
        // Gets all entities of type T
        IEnumerable<T> GetAll();
        // Gets entities using delegate
        IEnumerable<T> GetMany(Expression<Func<T, bool>> where);


    }
}

对象:\SGI2.Data\Infrastructure\RepositoryBase.cs

public virtual void Update(T entity)
{
    dbSet.Attach(entity); ! The error is thrown here !
    dataContext.Entry(entity).State = EntityState.Modified;
}

我能做些什么来解决? 我想要的是两次调用:_service.UpdateProjeto

致以诚挚的问候 伊莎贝尔·丰塞卡

c# entity-framework
© www.soinside.com 2019 - 2024. All rights reserved.