C# Razor pages ef core-CRUD如何在编辑时修改嵌套集合?DBConcurrencyException
在我的项目中,我将LazyLoading与EF Core结合使用,我有两个实体:C# Razor pages ef core-CRUD如何在编辑时修改嵌套集合?DBConcurrencyException,c#,asp.net,entity-framework,razor,entity-framework-core,C#,Asp.net,Entity Framework,Razor,Entity Framework Core,在我的项目中,我将LazyLoading与EF Core结合使用,我有两个实体: public class OfferEntity : BaseEntity { public string Category { get; set; } public virtual List<ImagePreviewEntity> ImagePreviews { get; set; } } public class ImagePre
public class OfferEntity : BaseEntity
{
public string Category { get; set; }
public virtual List<ImagePreviewEntity> ImagePreviews { get; set; }
}
public class ImagePreviewEntity: BaseEntity
{
public string PreviewUrl { get; set; }
}
有两个问题我无法解决:
我错过了什么?在与EF斗争了一天之后,找到了一个不优雅但有效的解决方案。 其中一些问题是:
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
return Page();
var newImages = OfferEntity.ImagePreviews
.Where(x => string.IsNullOrEmpty(x.Id))
.ToList();
foreach (var imagePreviewEntity in newImages)
{
imagePreviewEntity.Id = Guid.NewGuid().ToString();
await _context.ImagePreviews.AddAsync(imagePreviewEntity);
}
_context.Attach(OfferEntity).State = EntityState.Modified;
var relatedPreviewIds = OfferEntity.ImagePreviews.Select(x => x.Id).ToList();
var previews = await _context.ImagePreviews
.Where(x => relatedPreviewIds.Contains(x.Id))
.ToListAsync();
previews.ForEach(entity =>
{
_context.Entry(entity).CurrentValues.SetValues(OfferEntity.ImagePreviews.First(p => p.Id == entity.Id));
if (string.IsNullOrEmpty(entity.PreviewUrl))
{
_context.Attach(entity).State = EntityState.Deleted;
return;
}
if (_context.Entry(entity).State != EntityState.Added)
_context.Attach(entity).State = EntityState.Modified;
});
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
if (!OfferEntityExists(OfferEntity.Id))
return NotFound();
throw;
}
return RedirectToPage("./Index");
}
公共异步任务OnPostAsync()
{
如果(!ModelState.IsValid)
返回页();
var newImages=OfferEntity.ImagePreviews
.Where(x=>string.IsNullOrEmpty(x.Id))
.ToList();
foreach(新图像中的var imagePreviewEntity)
{
imagePreviewEntity.Id=Guid.NewGuid().ToString();
wait_context.ImagePreviews.AddAsync(imagePreviewEntity);
}
_Attach(OfferEntity).State=EntityState.Modified;
var relatedPreviewWids=OfferEntity.ImagePreviews.Select(x=>x.Id.ToList();
var previews=wait_context.ImagePreviews
.Where(x=>relatedPreviewWids.Contains(x.Id))
.ToListAsync();
previews.ForEach(实体=>
{
_context.Entry(entity).CurrentValues.SetValues(OfferEntity.ImagePreviews.First(p=>p.Id==entity.Id));
if(string.IsNullOrEmpty(entity.PreviewUrl))
{
_context.Attach(entity).State=EntityState.Deleted;
返回;
}
if(_context.Entry(entity.State!=EntityState.Added)
_context.Attach(entity.State=EntityState.Modified;
});
尝试
{
wait_context.SaveChangesAsync();
}
捕获(DbUpdateConcurrencyException ex)
{
如果(!OfferEntityExists(OfferEntity.Id))
返回NotFound();
投掷;
}
返回页首(“/索引”);
}
我觉得一定有更干净的解决办法。为了从嵌套列表中添加/删除实体而编写尽可能多的代码是愚蠢的
public async Task<IActionResult> OnGetAsync(string id)
{
OfferEntity = await _context.Offers.Include(x => x.ImagePreviews).FirstOrDefaultAsync(m => m.Id == id);
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
return Page();
//await _context.Offers.Include(p => p.ImagePreviews).LoadAsync();
var toRemove = OfferEntity.ImagePreviews
.Where(x => string.IsNullOrEmpty(x.PreviewUrl))
.ToList();
_context.Attach(OfferEntity).State = EntityState.Modified;
_context.ImagePreviews.RemoveRange(toRemove);
await _context.SaveChangesAsync();
return return RedirectToPage("./Index");
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
return Page();
var newImages = OfferEntity.ImagePreviews
.Where(x => string.IsNullOrEmpty(x.Id))
.ToList();
foreach (var imagePreviewEntity in newImages)
{
imagePreviewEntity.Id = Guid.NewGuid().ToString();
await _context.ImagePreviews.AddAsync(imagePreviewEntity);
}
_context.Attach(OfferEntity).State = EntityState.Modified;
var relatedPreviewIds = OfferEntity.ImagePreviews.Select(x => x.Id).ToList();
var previews = await _context.ImagePreviews
.Where(x => relatedPreviewIds.Contains(x.Id))
.ToListAsync();
previews.ForEach(entity =>
{
_context.Entry(entity).CurrentValues.SetValues(OfferEntity.ImagePreviews.First(p => p.Id == entity.Id));
if (string.IsNullOrEmpty(entity.PreviewUrl))
{
_context.Attach(entity).State = EntityState.Deleted;
return;
}
if (_context.Entry(entity).State != EntityState.Added)
_context.Attach(entity).State = EntityState.Modified;
});
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
if (!OfferEntityExists(OfferEntity.Id))
return NotFound();
throw;
}
return RedirectToPage("./Index");
}