我刚开始使用linq和实体框架,我有一个对所有高级用户都显得天真的问题!
我有以下代码:
var allDocuments = (from i in companyData.IssuedDocuments select i.IssuedDocumentId).ToList<int>();
var deletedDocuments = allDocuments.Except(updatedDocuments);
我需要删除companyData中所有实体,这些实体的ID在断开连接的场景中存储在deletedDocuments中。
请您以高效的方式告诉我一种方法吗?
答案 0 :(得分:1)
您可以通过指定只想要删除的ID来避免获取所有ID:
var deletedIds = from i in companyData.IssuedDocuments
where !updatedIds.Contains(i.IssuedDocumentId)
select i.IssuedDocumentId
现在,如果companyData.IssuedDocuments
是DbSet
,您可以告诉EF删除它们:
foreach (var id in deletedIds)
{
var entity = new MyEntity { Id = id };
companyData.IssuedDocuments.Attach(entity);
companyData.IssuedDocuments.Remove(entity);
}
dbContext.SaveChanges();
这将向数据库发出多个DELETE语句,而不会将完整实体提取到内存中。
如果companyData.IssuedDocuments
是您的存储库,那么您可以加载完整的实体而不仅仅是ID:
var deleted = from i in companyData.IssuedDocuments
where !updatedIds.Contains(i.IssuedDocumentId)
select i
foreach (var entity in deleted)
companyData.IssuedDocuments.Delete(entity);
dbContext.SaveChanges();
再次,EF向数据库发出多个DELETE语句
如果你可以升级,那么EF6在你可以看到的RemoveRange
上引入了DbSet
方法。它可能会向数据库发送一个DELETE语句 - 我还没有尝试过。
如果性能仍然存在问题,那么你必须执行sql。
参考文献:
答案 1 :(得分:0)
companyData.RemoveAll(x=>deletedDocuments.Contains(x.Id));
我认为companyData是IEnumerable类型。类型T包含Id属性,它是数据的Id。然后,deletedDocuments包含我们要删除的所有文档的ID。
有一件事很重要,我应该在这里注意到,文件的删除发生在内存中,而不是在db中执行。否则,您应该向我们提供您使用的实体框架的版本以及您如何访问您实现针对您的数据库的CRUD操作。
答案 2 :(得分:0)
首先,我要感谢大家的建议。
我遵循了Christos Paisios的建议,但当我试图将更改保存到数据库时,我遇到了各种异常,而我最终设法解决问题的方法是在我的DbContext类中添加以下覆盖
public override int SaveChanges()
{
var orphanedResponses = ChangeTracker.Entries().Where(
e => (e.State == EntityState.Modified || e.State == EntityState.Added) &&
e.Entity is IssuedDocument &&
e.Reference("CompanyData").CurrentValue == null);
foreach (var orphanedResponse in orphanedResponses)
{
IssuedDocuments.Remove(orphanedResponse.Entity as IssuedDocument);
}
return base.SaveChanges();
}