【问题标题】:Delete many records per ID - MVC C#删除每个 ID 的许多记录 - MVC C#
【发布时间】:2015-04-26 05:09:58
【问题描述】:

我的数据库设置是,Company 可以有多个Engineer,也可以有多个Territory。如果我应该从列表中删除一家公司,我需要彻底退出,所以不要只从公司表中删除公司。我必须确保所有记录都被删除。因此,没有子/相关记录成为孤立数据。

如果我要从所有表中删除一条记录,我只需使用FirstOrDefault 删除它,然后我可以使用

public void RemoveCompany(long companyId)
{
    using (var db = new BoilerServicingDbContext())
    {
        var ec = db.Engineers.FirstOrDefault(x => x.CompanyId == companyId);
        db.Engineers.Remove(ec);
        var tc = db.CompanyTerritories.FirstOrDefault(x => x.CompanyId == companyId);
        db.CompanyTerritories.Remove(tc);
        var p = db.Companies.FirstOrDefault(x => x.Id ==  companyId);
        db.Companies.Remove(p);
        db.SaveChanges();       
    }
}

但是,每个公司有多个工程师,每个公司有多个区域。有没有像一般数据库意义上的简单方法。

DELETE * FROM Engineers WHERE companyId = 1;

目前我没有级联删除设置,除此之外。任何其他选项。

【问题讨论】:

标签: c# asp.net-mvc entity-framework model-view-controller cascade


【解决方案1】:

为什么不使用.Where() 方法来查找数据库中的所有对应项?像这样:

foreach(var ec in db.Engineers.Where(x => x.CompanyId == companyId))
{
    db.Engineers.Remove(ec);
}
// same logic here for other tables

还要考虑@workabyte 答案,因为有一种方法可以在您的数据库中实现cascade delete

【讨论】:

  • 我想象有一种更简单的方法可以在一行中删除。不过,这已经为我完成了。非常感谢!
  • 还要考虑@workabyte 的答案,因为有一种方法可以在您的数据库中实现cascade delete
  • 当然。 Cascade on Delete 是第一个选项,但我不确定是否还有其他可能性。 :)
  • 我在 C# 聊天室中提出了这个问题,普遍的共识是使用 ORM 进行批处理操作可能是个坏主意,您应该改用存储命令。
  • 我个人更喜欢不使用 ORM :)
【解决方案2】:

一个选项可以在删除时级联,您必须告诉 EF 为您执行此操作,因为默认情况下它不会这样做,这样的事情应该这样做。还链接到其他一些对额外阅读具有类似吸引力的 SO 答案。

modelBuilder.Entity<Company>()
        .HasMany(b => b.Engineer)
        .WillCascadeOnDelete(true);

https://stackoverflow.com/a/9241880/546411

https://stackoverflow.com/a/14493591/546411

【讨论】:

  • 谢谢,我可能会在删除时将其设为级联。此时,我正在尝试通过代码删除。 :)
  • @PaulFrancis,您将通过代码删除父记录,这将导致其余记录被删除,这样您就不必遍历一堆记录。代码很好,很高兴你找到了答案
  • 是的,当然。我刚开始接触 C#,所以学习所有可能性。由于删除时的级联是很容易实现的,所以我在想所有其他扭曲的方式。 ;) +1 为我提供替代答案! :)
【解决方案3】:

如果您不介意使用表名,请使用普通 SQL(最有效):

public void RemoveCompany(long companyId)
{
    using (var db = new BoilerServicingDbContext())
    {
        var engineerIds = db.Engineers
                            .Where(x => x.CompanyId == companyId)
                            .Select(x => x.Id).ToList();

        var sql  = "DELETE FROM Engineers WHERE Id IN ({0})";
        sql = string.Format(sql, string.Join(", ", engineerIds);
        db.Database.ExecuteSqlCommand(sql);
        db.SaveChanges();       
    }
}

【讨论】:

  • 只是好奇,不攻击。你能详细说明这种方法的效率吗?
  • 它并不比级联删除更有效,但比每次删除生成一条 SQL 语句更有效。 (也不会映射工程师对象层次结构(如果有的话))
【解决方案4】:

看看这个link。 它是一个扩展 EF 并(除其他外)提供批量更新/删除方法的库。

在你的情况下:

int companyid = 1;

context.Engineers.Delete(x=>x.CompanyId == companyid)
context.CompanyTerritories.Delete(x=>x.CompanyId == companyid)
context.Companies.Delete(x=>x.CompanyId == companyid)

【讨论】:

    【解决方案5】:

    在 EF6 中使用 RemoveRange 并且不使用 foreach 会容易得多:

    db.Engineers.RemoveRange(db.Engineers.Where(x => x.CompanyId == companyId));
    db.SaveChanges();
    

    【讨论】:

      猜你喜欢
      • 2021-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-28
      • 2020-09-28
      相关资源
      最近更新 更多