问题描述
我正在尝试使用实体框架更新实体,但是,每次我尝试这样做时,都会引发错误,指出无法跟踪主类包含的嵌套实体。
这些是我的课程:
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();
}
我做错了什么吗?我已经坚持了一个星期了...
在此先感谢并为长篇大论感到抱歉,但我希望它清楚。
解决方法
我终于可以通过在我的存储库的 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);
}