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();