【问题标题】:How to perform deletion of entities based on a list of ids如何根据 id 列表执行删除实体
【发布时间】:2014-01-03 04:26:23
【问题描述】:

我只是从一般的 linq 和实体框架开始,我有一个对于所有高级用户来说可能看起来很幼稚的问题!

我有以下代码:

var allDocuments = (from i in companyData.IssuedDocuments select i.IssuedDocumentId).ToList<int>();
var deletedDocuments = allDocuments.Except(updatedDocuments);

并且我需要在断开连接的情况下删除 companyData 中其 id 存储在 deletedDocuments 中的所有实体。

您能告诉我一种有效的方法吗?

【问题讨论】:

    标签: linq entity-framework


    【解决方案1】:

    您可以通过指定您只想要删除的 ID 来避免获取所有 ID,如下所示:

    var deletedIds = from i in companyData.IssuedDocuments 
                     where !updatedIds.Contains(i.IssuedDocumentId)
                     select i.IssuedDocumentId
    

    现在如果 companyData.IssuedDocumentsDbSet 你可以告诉 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 在 DbSet 上引入了 RemoveRange 方法,您可以查看。它可能会向数据库发送一条 DELETE 语句 - 我还没有尝试过。

    如果性能仍然是一个问题,那么您必须执行 sql。

    参考资料:

    RemoveRange

    Deleting an object without retrieving it

    How should I remove all elements in a DbSet?

    【讨论】:

      【解决方案2】:
      companyData.RemoveAll(x=>deletedDocuments.Contains(x.Id));
      

      我想 companyData 是一个 IEnumerable 类型。类型 T 包含一个 Id 属性,它是数据的 Id。然后 deletedDocuments 包含我们要删除的所有文档的 id。

      有一点很重要,我应该在这里注意的是,文档的删除发生在内存中,并且不会在数据库中执行。否则,您应该向我们提供您使用的实体框架的版本以及您如何访问您对您的数据库实施 CRUD 操作。

      【讨论】:

      • 我使用实体框架 5.0 并使用 UoW 模式访问数据库。在内存中工作的代码是 companyData.IssuedDocuments.RemoveAll(x => deletedDocuments.Contains(x.IssuedDocumentId));但这不会将记录标记为从数据库中删除
      • @gnl 由于您使用的是 UoW 模式,因此将有一个关于 companyData 类型的 CRUD 操作的存储库类。正确的?你能不能给我这门课。在本课程中,我将看到您实现有关 companyData 实体的 CRUD 操作。谢谢!
      【解决方案3】:

      首先感谢大家的建议。

      我遵循了 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();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-10
        • 1970-01-01
        • 1970-01-01
        • 2019-01-20
        • 2012-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多