我的问题基于类似的问题,但增加了分页的复杂性。
public class Parent
{
public Parent()
{
this.Children = new List<Child>();
}
public int Id { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Data { get; set; }
}
假设 Children 集合有 1000 条记录:
{ 1, 2, 3, ... 998, 999, 1000 }
public Parent Get(int parentId, int childrenPageSize)
{
var existingParent = _dbContext.Parents
.Where(p => p.Id == parentId)
.Include(p => p.Children.Take(childrenPageSize))
.AsNoTracking()
.SingleOrDefault();
}
通过分页,我们只取前 10 个子项:
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
用户然后在前端应用程序中编辑 Parent 对象,并删除集合中的 2 个子对象,然后单击“保存”以更新父对象:
{ 3, 4, 5, 6, 7, 8, 9, 10 }
我在存储库类中使用 Update 方法
public void Update(UpdateParentModel model)
{
var existingParent = _dbContext.Parents
.Where(p => p.Id == model.Id)
.Include(p => p.Children)
.SingleOrDefault();
// Delete children
foreach (var existingChild in existingParent.Children.ToList())
{
if (!model.Children.Any(c => c.Id == existingChild.Id))
_dbContext.Children.Remove(existingChild);
}
}
问题:当实体框架加载existingParent时,它会急切地加载1000个子级的整个集合。模型参数包含 8 个子项的集合,其中两个已被删除。我如何告诉实体框架仅删除已删除的 2 个子项?
注意:我想避免使用 ExecuteDelete、RawSQL 或存储过程。我需要能够调用 _dbContext.SaveChangesAsync()。
UpdateParentModel
应包含 IEnumerable<int>
的属性,表示要删除的 Child
对象的 ID。然后,您可以附加一个已删除的新 Child
对象,仅使用为该可枚举属性中的每个 ID 值设置的 ID 值,从而无需从数据库加载任何内容。
您用于操作的模型不需要与它们所作用的一个或多个实体相匹配。以最有用/最高效的方式打包数据。
foreach( var childId in model.RemovedChildIDs )
{
var entry = dbContext.Attach( new Child
{
Id = childId,
} );
entry.State = EntityState.Deleted;
}
…
dbContext.SaveChangesAsync();