如何更新具有嵌套实体列表的现有实体?

问题描述

我正在尝试使用实体框架更新实体,但是,每次我尝试这样做时,都会引发错误,指出无法跟踪主类包含的嵌套实体。

这些是我的课程:

 public abstract class BaseEntity
 {
     public int Id { get; set; }
 }
 public class Dashboard : BaseEntity
 {
     public int Order { get; set; }
     public string Title { get; set; }
     public bool Enabled { get; set; }
     public virtual ICollection<Submenu> Submenu { get; set; }
 }
public class Submenu : BaseEntity
{
    public int Order { get; set; }
    public bool Enabled { get; set; }
    public string Title { get; set; }
    public string Image { get; set; }
    public string Descriptions { get; set; }
    public virtual ICollection<Action> Actions { get; set; }
    public int DashboardId { get; set; }
    public virtual Dashboard Dashboard { get; set; }
}

public class Action : BaseEntity
{
    public string Type { get; set; }
    public string Label { get; set; }
    public string Url { get; set; }
    public string Extension { get; set; }

    public virtual Submenu Submenu { get; set; }
    public int SubmenuId { get; set; }
}

我用来更新的是仪表板,它包含其余的类。

我正在尝试使用以这种方式定义的通用服务层和通用存储库:


public class GenericService<T> : IGenericService<T> where T : BaseEntity
{
    private readonly IBaseRepository<T> baseRepository;

    public GenericService(IBaseRepository<T> baseRepository)
    {
        this.baseRepository = baseRepository;
    }

    public async Task Update(T entity,T attachedEntity)
    {
        await baseRepository.Update(entity,attachedEntity);
    }
}

public class BaseRepository<T> : IBaseRepository<T> where T : BaseEntity
{
    private readonly PortalContext dataContext;

    private DbSet<T> DbSet { get; set; }

    public BaseRepository(PortalContext context)
    {
        dataContext = context;
        DbSet = dataContext.Set<T>();
    }

    public async Task Update(T entity,T attachedEntity)
    {
        dataContext.Entry(attachedEntity).State = EntityState.Detached;
        DbSet.Attach(entity);
        dataContext.Entry(entity).State = EntityState.Modified;
        await dataContext.SaveChangesAsync();
    }
}

而且,最后但同样重要的是,这就是我在 Startup.cs 中配置所有内容的方式

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<PortalContext>(
        options => options.UsesqlServer(Configuration.GetConnectionString("PortalContext"))
    );
    
    services.AddTransient(typeof(IGenericService<>),typeof(GenericService<>));
    services.AddTransient(typeof(IBaseRepository<>),typeof(BaseRepository<>));
    
    services.AddTransient<Func<string,ClaimsPrincipal,IRoleCheck>>((serviceProvider) =>
    {
        return (controllerName,claimsPrincipal) =>
                new RoleCheck(serviceProvider.GetrequiredService<IGenericService<Dossier>>(),serviceProvider.GetrequiredService<IGenericService<DossierTemplate>>(),serviceProvider.GetrequiredService<IGenericService<Dashboard>>(),controllerName,claimsPrincipal);
    });
}

应用程序首先要做的是调用 RoleCheck 类来检索和过滤所需的实体,然后用户可以更新它们。

当我在控制器上调用更新函数

 public async Task<ActionResult<Dashboard>> Put(int id,[FromBody] Dashboard dashboard)
 {
     var currentDashboard = await service.Get(id);
     if (currentDashboard == null)
     {
         return NotFound();
     }
    
     await service.Update(dashboard,currentDashboard);
     return Ok();

}

我总是在存储库中收到下​​一个错误error

我做错了什么吗?我已经坚持了一个星期了...

在此先感谢并为长篇大论感到抱歉,但我希望它清楚。

解决方法

我终于可以通过在我的存储库的 Get() 方法中添加 .AsNoTracking() 来解决它:

public async Task<T> Get(int id,Func<IQueryable<T>,IIncludableQueryable<T,object>> includes)
{
    IQueryable <T> query = DbSet.AsNoTracking();
    if (includes != null)
    {
        query = includes(query);
    }
    return await query.FirstOrDefaultAsync(m => m.Id == id);
}