2017-03-29 105 views
3

我有一個具有一對多關係的數據庫表[Table1]。
這個相關的表[Table2]有一個類型字段,它是一個字符串。linq-to-sql按連接表中的字符串列表組

 
Table 1   Table 2 
Field | Type  Field | Type 
------|-----  ---------|----- 
Id | int  Id  | int 
       Table1Id | int 
       Type  | string 

我想創建的類型的每個組合出現的頻率, 的總結和我試圖做的DB儘可能多的工作,因爲它是把一切都寫進內存太慢。

代碼我有工作,但似乎重複我。

 items 
     .Where(x => x.Table2s.Count > 1) 
     .Select(x => new 
     { 
      Type = x.Table2s.Select(y => y.Type) 
     }) 
     .ToList() // into memory as string.join has no translation into sql 
     .Select(x => new 
     { 
      Type = string.Join(",", x.Type) // no sql translation 
     }) 
     .GroupBy(x => x.Type) // can't work on IEnumerable[string] 
     .Select(x => new Result() 
     { 
      Type = x.Key, 
      Count = x.Count() 
     }) 
     .OrderByDescending(x => x.Count) 
     .ToList(); 

有沒有一種辦法按該字符串列表,這樣我可以做的DB分組,並減少在我的代碼

+1

爲什麼你'的string.join()'所有類型和組在那?你是否試圖檢測具有相同字段定義的類型的重複項? –

+0

@JeroenvanLangen對不起,我試圖顯示table1中的記錄已鏈接到表2類型的每種組合的次數: 類型a,b,c = 5 |類型a,c = 10 |類型d,f = 1 –

+0

您可以將一個int字段添加到「表1」中,通過該字段可以製作標記枚舉的類型元素。然後你可以按他們的總數分組。 –

回答

0

LINQ到SQL不支持select語句的數量AggregateString.Join或相應的SQL技巧,所以除非你想使用存儲過程,否則一些工作必須發生在客戶端。

另一種方法是首先創建分組,然後將它們發送回服務器以計算匹配,但這看起來不像是一種收益。

我認爲你能做的最好的是一樣的東西

var sqlans = items.Where(x => x.Table2s.Count > 0).AsEnumerable(); 
var ans = sqlans.Select(x => String.Join(",", x.Table2s.Select(t2 => t2.Type).OrderBy(ty => ty).ToArray())).GroupBy(ty => ty, ty => ty, (key, g) => new { key, Count = g.Count() }); 

我下令Type小號屬於一個item所以分組時,他們會匹配。 sqlans部分將由服務器執行,但其餘部分必須在客戶端上執行以處理String.Join

而不是使用EF我會被誘惑到工作表2的(做左半加入,如果你可能有孤兒表2項)直接

var sqlans = Table2.GroupBy(t2 => t2.Table1Id, t2 => t2.Type, (key, g) => g).AsEnumerable(); 
var ans = sqlans.Select(x => String.Join(",", x.OrderBy(ty => ty).ToArray())).GroupBy(ty => ty, ty => ty, (key, g) => new { key, Count = g.Count() });