Asp.net core 如何更新具有嵌套实体列表的现有实体?
我尝试使用entity framework更新实体,但每次尝试更新时,都会引发一个错误,表示无法跟踪主类包含的嵌套实体 这些是我的课程:Asp.net core 如何更新具有嵌套实体列表的现有实体?,asp.net-core,entity-framework-core,entity-framework-core-2.1,Asp.net Core,Entity Framework Core,Entity Framework Core 2.1,我尝试使用entity framework更新实体,但每次尝试更新时,都会引发一个错误,表示无法跟踪主类包含的嵌套实体 这些是我的课程: public abstract class BaseEntity { public int Id { get; set; } } 我用来更新的是Dashboard,它包含其余的类 我尝试使用一个通用服务层和一个通用存储库来实现这一点,它们的定义如下: public class GenericService<T> : IGener
public abstract class BaseEntity
{
public int Id { get; set; }
}
我用来更新的是Dashboard,它包含其余的类
我尝试使用一个通用服务层和一个通用存储库来实现这一点,它们的定义如下:
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);
}
}
公共类GenericService:IGenericService其中T:BaseEntity
{
专用只读IBaseRepository存储库;
公共泛型服务(IBaseRepository baseRepository)
{
this.baseRepository=baseRepository;
}
公共异步任务更新(T实体、T附件身份)
{
等待baseRepository.Update(实体、附件);
}
}
public类BaseRepository:IBaseRepository其中T:BaseEntity
{
私有只读PortalContext dataContext;
私有DbSet DbSet{get;set;}
公共基本存储库(PortalContext上下文)
{
dataContext=context;
DbSet=dataContext.Set();
}
公共异步任务更新(T实体、T附件身份)
{
条目(AttacheIdentity).State=EntityState.Distached;
附加数据集(实体);
dataContext.Entry(entity).State=EntityState.Modified;
等待dataContext.SaveChangesSync();
}
}
最后,但并非最不重要的一点是,这就是我在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);
});
}
public void配置服务(IServiceCollection服务)
{
services.AddDbContext(
options=>options.UseSqlServer(Configuration.GetConnectionString(“PortalContext”))
);
AddTransient(typeof(IGenericService)、typeof(GenericService));
AddTransient(typeof(IBaseRepository)、typeof(BaseRepository));
services.AddTransient((serviceProvider)=>
{
return(controllerName,claimsPrincipal)=>
新建RoleCheck(serviceProvider.GetRequiredService(),
serviceProvider.GetRequiredService(),
serviceProvider.GetRequiredService(),
控制人姓名、索赔人姓名);
});
}
应用程序首先要做的是调用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);
}
public异步任务Get(int-id,Func-includes)
{
IQueryable query=DbSet.AsNoTracking();
如果(包括!=null)
{
查询=包括(查询);
}
返回wait query.FirstOrDefaultAsync(m=>m.Id==Id);
}
我建议在附加失败时捕获此异常,并使用Find
在ChangeTracker中查找已注册的实体。Get与更新有什么关系?您必须修复更新方法。
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();
}
}
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);
});
}
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();
}
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);
}