EF 错误:无法跟踪实体类型“对象”的实例,因为另一个实例

时间:2021-01-31 21:03:25

标签: c# asp.net-core entity-framework-core blazor-server-side

我对这个和 Blazor 的新手感到茫然,并试图学习它 (.NET 5)

我有一个简单的模型:

public class Status
{
    [Key]
    public int Id { get; set; }
    
    [Required]
    public string Name { get; set; }
    public DateTime CreatedOn { get; set; }
    public DateTime LastUpdatedOn { get; set; }
}

Startup.cs 中,我注册了我的数据库和服务。

 services.AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("Default")),(ServiceLifetime.Scoped));

 services.AddAutoMapper(typeof(Startup));
 services.AddScoped<IStatusRepo, StatusRepo>();
 services.AddScoped<IStatusService, StatusService>();

我的组件的文件隐藏代码如下。 GetStatus 调用返回的 dto 与更新状态服务方法接受的不同,因此我在 UpdateStatus 方法中对其进行了转换。

public partial class EditStatus : ComponentBase
{
        [Parameter]
        public int StatusId { get; set; }

        [Inject]
        IStatusService StatusService { get; set; }

        [Inject]
        NavigationManager navigationManager { get; set; }

        public bool ShowLoadError { get; set; } = false;
        private StatusDetailDto StatusToEdit { get; set; } = new StatusDetailDto();

        protected override async Task OnInitializedAsync()
        {
            await GetStatusToEdit(StatusId);
        }

        public async Task GetStatusToEdit(int statusId)
        {
            try
            {
                StatusToEdit = await StatusService.GetStatusById(statusId);
            }
            catch (Exception ex)
            {
                ShowLoadError = true;
            }
        }

        protected async void UpdateStatus()
        {
            UpdateStatusDto updatedStatus = new UpdateStatusDto();
            updatedStatus.Id = StatusToEdit.Id;
            updatedStatus.Name = StatusToEdit.Name;

            StatusDetailDto statusUpdated = await StatusService.UpdateStatus(updatedStatus);

            if (statusUpdated != null)
            {
                navigationManager.NavigateTo("status/manage");
            }
            else
            {
                Console.WriteLine("No here");
            }
        }
    }

服务层为:

public async Task<StatusDetailDto> UpdateStatus(UpdateStatusDto statusDto)
{
    Status statusToUpdate = mapper.Map<UpdateStatusDto, Status>(statusDto);
    Status updatedStatus = await statusRepo.UpdateStatus(statusToUpdate);
    return mapper.Map<Status, StatusDetailDto>(updatedStatus);
}

和回购

public async Task<Status> UpdateStatus(Status Status)
{
   if (Status is null) 
        throw new ArgumentNullException("Nulls are not allowed.");

   try
   {
        Status.LastUpdatedOn = DateTime.Now;

        // THIS LINE THROWS THE ERROR!
        _dbContext.Entry(Status).State = EntityState.Modified; 

        await _dbContext.SaveChangesAsync();
        return Status;
    }
    catch (Exception)
    {
        throw;
    }
}

也许我的服务寿命有误?我也为我的 dbcontext 尝试过短暂的生命周期。什么会抛出这个错误?

<块引用>

无法跟踪实体类型 'Status' 的实例,因为已跟踪另一个具有相同 {'Id'} 键值的实例。

1 个答案:

答案 0 :(得分:0)

首先通过从 AddDBContext 中删除 ServiceLifetime.Scoped 来修复启动文件

services.AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("Default")));

然后更改您的 UpdateStatus 代码

public async Task<Status> UpdateStatus(Status status)
{
   if (status is null) throw new ArgumentNullException("Nulls are not allowed.");
   try
   {
    var existedItem=_dbContext.Set<Status>().FirstOrDefaultAsync(i=i.Id==status.id);
       if(existedItem==null) throw new ArgumentNullException("Item is not found.");
      existedItem.LastUpdatedOn = DateTime.Now;
      _dbContext.Entry(existedItem).State = EntityState.Modified; 
      await _dbContext.SaveChangesAsync();
      return Status;
    }
    catch (Exception)
    {
      throw;
    }
}
相关问题