2014-11-21 49 views
3

我在編寫linq查詢時遇到了麻煩,因爲我對它不熟悉。我有兩個表RosterSummaryData_Subject_LocalRosterSummaryData_Subject_Local_Bands在其他表中刪除沒有參考的行

Subject_Local包含pkSummarySubjectLocalIDSubject_Local_Bands包含一個外鍵參照該表(fkSummarySubjectlocalID)。 Subject_Local包含永遠不會使用的未使用或孤行行。我想要做的是刪除未使用/孤立的行,如果它們不在Subject_Local_Bands中。

例如,如果我們看看這些示例表:

RosterSummaryData_Subject_Local  RosterSummaryData_Subject_Local_Bands 
pkSummarySubjectLocalID    pkSummarySubjectLocalBandID fkSummarySubjectLocalID Score 
1          1       2      10 
2          2       4      20 
3          3       5      30 
4 
5 

在這兩個表可以看出,在Subject_Local.pkSummarySubjectLocalIDs 1和3從不Subject_Local_Bands引用。我想從Subject_Local中刪除它們。

這是我目前的LINQ代碼不

var local = customerContext.RosterSummaryData_Subject_Local; 
var localBands = customerContext.RosterSummaryData_Subject_Local_Bands; 
IEnumerable<RosterSummaryData_Subject_Local> redundantSubjectLocalRows; 

redundantSubjectLocalRows = from subjLocal in customerContext.RosterSummaryData_Subject_Local 
          join subjLocalBands in customerContext.RosterSummaryData_Subject_Local_Bands on 
           subjLocal.pkSummarySubjectLocalID equals subjLocalBands.fkSummarySubjectLocalID 
          where subjLocalBands.fkSummarySubjectLocalID != subjLocal.pkSummarySubjectLocalID 
          select subjLocal.pkSummarySubjectLocalID; 

customerContext.RosterSummaryData_Subject_Local.RemoveRange(redundantSubjectLocalRows); 

我想用RemoveRange所以我需要通過它在我的上下文類RosterSummaryData_Subject_LocalIEnumerable工作,但我不知道如何創建一個使用一個完成指定條件的linq查詢。任何幫助?

回答

2
var local = customerContext.RosterSummaryData_Subject_Local; 
var localBands = customerContext.RosterSummaryData_Subject_Local_Bands; 

您應該使用except。除B外的所有值都返回A中但不包含在B中的所有值 我們選擇除localBands.fkSummarySubjectLocalID之外的所有local.pkSummarySubjectLocalID,結果全部爲pkSummarySubjectLocalID,它們在local中,但不在localBands中。

var orphanedIds = local.Select(x => x.pkSummarySubjectLocalID) 
         .Except(localBands.Select(x => x.fkSummarySubjectLocalID)); 

那麼我們加入這個結果(orphanedIds)與local並得到所有孤兒local S的。

var orphaned = from l in local 
     join id in orphanedIds on l.pkSummarySubjectLocalID equals id 
     select l; 

現在是時候刪除所有孤兒local秒。

local.RemoveRange(orphaned); 
customerContext.SaveChanges(); 
+0

我最喜歡你的答案,除了它似乎只帶回在Subject_Local_Band中引用的行(這些是我想保留的ID)我想要的是相反的。我翻轉了相交,但我仍然有相同的結果。 – frontin 2014-11-21 21:30:44

+0

問題是一個錯字,我想用除了但我說相交,修正,這種方法是用數據庫端的sql quesries完成的,其他的方法是從db中取得很多數據。 – dotctor 2014-11-22 06:39:18

+1

不情願我得到upvote這個答案,這是肯定性感比我沉悶的錘子方法:-)'除()'嗯?每天學些新東西... – 2014-11-22 19:22:04

2

可以說不雅,但這應該是有效的:

HashSet<int> unorphanedIds new HashSet<int>( 
    RosterSummaryData_Subject_Local_Bands 
    .Select(b=>b.fkSummarySubjectLocalID)); 

var toRemove = customerContext.RosterSummaryData_Subject_Local 
    .Where(r=>!unorphanedIds.Contains(r.pkSummarySubjectLocalID)); 

customerContext.RosterSummaryData_Subject_Local.RemoveRange(toRemove); 
customerContext.SaveChanges(); 
+0

嘿謝謝你。它的優雅夠我:) – frontin 2014-11-21 21:51:34

1

瑞安,

您可以使用下面的語句從您的LINQ查詢創建RosterSummaryData_Subject_Local類。

public void TestMethod() 
{ 
    DataSet lDataSet = new DataSet(); 

    var lOutput = (from lRosterSummaryBand in lDataSet.Tables[0].AsEnumerable() 
        select new RosterSummaryData_Subject_Local 
        { 
         //Assign the field value for each row to the model property specified. 
         //Make sure to use the correct data types specified from the data base. 
         pkSummarySubjectLocalID = lRosterSummaryBand.Field<System.Int64>("pkSummarySubjectLocalID") // Column name from DataTable/DataSet 
        }).ToList();//Make sure to set the output as an enumeration 
} 

的數據存儲在一個變種集合,但你可以施放它們作爲對象()。

值得注意的是,當LINQ爲這個var集合賦值時,它通過引用而不是值來完成它。對var所做的任何更改都會改變DataTable/DataSet。

或者,您也可以執行以下操作。這會留下連接你的兩個表,將它們分配給模型,並只選擇你的子表爲空/無值的行。

var lRowsMarketForDeletion = (from lSubjectLocal in lDataSet.Tables[0].AsEnumerable() 
             join lSubjectLocalbands in lDataSet.Tables[1].AsEnumerable() on lSubjectLocal.Field<System.Int64>("pkSummarySubjectLocalID") equals lSubjectLocalbands.Field<System.Int64>("pkSummarySubjectLocalID") into lJoinedGroup 
             from lJoinedRow in lJoinedGroup.DefaultIfEmpty(new RosterSummaryData_Subject_Local { pkSummarySubjectLocalID = 0 }) 
             where lJoinedRow.pkSummarySubjectLocalID == 0 
             select new RosterSummaryData_Subject_Local 
             { 
              pkSummarySubjectLocalID = lRosterSummaryBand.Field<System.Int64>("pkSummarySubjectLocalID") 
             }).ToList(); 

customerContext.RosterSummaryData_Subject_Local.RemoveRange(lRowsMarketForDeletion); 

參考文獻:

http://msdn.microsoft.com/en-us/library/bb311040.aspx連接表。

linq to sql using select new inside class file爲每一行選擇一個新的對象。

http://www.dotnet-tricks.com/Tutorial/linq/UXPF181012-SQL-Joins-with-C左連接如何工作。

讓我知道你是否需要別的東西。