2

我对数据库的设置是,Company可以有很多Engineer,并且可以在很多Territory中。如果我应该从列表中删除一个公司,我需要做一个干净的退出,所以不要删除公司表格中的公司表格。我必须确保所有记录都被删除。所以没有儿童/相关记录成为孤儿数据。每个ID删除多条记录 - MVC C#

如果我从所有的表中删除一条记录,我会用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; 

在这一刻我没有层叠删除设置,所以除此之外。任何其他选项。

+2

https://msdn.microsoft.com/en-us/data/jj592907.aspx – CodeCaster 2015-02-24 14:20:14

+0

谢谢@CodeCaster,我将在EF工作后看看SQL版本。非常感激 ! – PaulFrancis 2015-02-24 14:29:42

回答

6

为什么不用.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的方式。

+0

我想象一下,有一种更简单的方法可以删除一行。虽然这已经为我做了。真的非常感谢你 ! – PaulFrancis 2015-02-24 14:26:21

+0

另外考虑@workabyte的答案,因为有一种方法可以在数据库中实现'cascade delete'。 – VMAtm 2015-02-24 14:32:55

+0

绝对如此。删除级联是第一个选项,但我不确定是否还有其他可能。 :) – PaulFrancis 2015-02-24 14:35:15

2

一个选项可以级联删除,你必须告诉EF为你做这件事,因为它不会默认,这样的事情应该这样做。还有一些其他的答案与一些额外阅读有类似的吸引力的答案。

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

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

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

+0

谢谢,我可能会将它删除级联。在这个时候,我试图通过代码删除。 :) – PaulFrancis 2015-02-24 14:27:27

+2

@PaulFrancis,你会通过代码删除父记录,这会导致其余的删除,这样你就不必循环一堆记录。代码不错,很高兴你找到答案 – workabyte 2015-02-24 14:29:15

+2

是的,绝对。我只是让我的牙齿进入C#,所以学习所有的可能性。由于级联删除是非常容易实现的,所以我在考虑所有其他扭曲的方式。 ;)+1为我提供备用答案! :) – PaulFrancis 2015-02-24 14:31:18

0

看看这个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) 
2

使用普通的SQL,如果你不介意使用的表名(最有效):使用RemoveRange

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();  
    } 
} 
+0

只是好奇,而不是攻击。你能详细说明这种方法的效率吗? – workabyte 2015-02-24 15:10:50

+2

它不比级联删除更有效,但比每次删除生成一条SQL语句更高效。 (也不会映射工程师对象层次结构(如果有的话)) – jgauffin 2015-02-24 15:19:09

0

在EF6它更容易和不含foreach:

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