2014-11-21 31 views
0

在EF模型使用這些類兩個表涉及做組:Linq查詢,通過與不直接連接

class BoxOutput 
{ 
    public long BoxId { get; set; } 
    public virtual Box Box { get; set; } 
    public long BoxId { get; set; } 
    public long CategoryId { get; set; } 
    public virtual Category Category { get; set; } 
    public long? ColorId { get; set; } 
    public virtual Category Color { get; set; } 
    public decimal Weight { get; set; } 

    // ...and other irrelevant properties 
} 

class BoxInput 
{ 
    public long BoxId { get; set; } 
    public virtual Box Box { get; set; } 
    public long BoxId { get; set; } 
    public long CategoryId { get; set; } 
    public virtual Category Category { get; set; } 
    public long? ColorId { get; set; } 
    public virtual Category Color { get; set; } 
    public decimal Weight { get; set; } 

    // ...and other irrelevant properties 
} 


......我該怎麼辦LINQ查詢,對於一個特定的盒(如boxId = 12),返回此?:

category.name color.name  inputWeightsSum  outputWeightsSum 
--------------------------------------------------------------------------- 
    c    null    0     0 
    c    red    0     0 
    c    blue    0     0 
    m    null    0     0 
    m    red    0     0 
    m    blue    0     0 
          .... 

我目前幾乎實現這一目標,但「可選顏色」是給做「笛卡爾積」當我的煩惱:我沒有顯示空。 ..

這就是我所擁有的。

var boxesInputs = dbContext.BoxesInputs 
.Where(c => c.BoxId == 12) 
.GroupBy(c => new { c.CategoryId, c.ColorId }) 
.Select(g => new 
{ 
    categoryId = g.Key.CategoryId, 
    colorId = g.Key.ColorId, 
    sumOfWeights = g.Sum(r => (decimal?)r.Weight) ?? 0, 
}).ToList(); 

var boxesOutputs = dbContext.BoxesOutputs 
.Where(c => c.BoxId == 12) 
.GroupBy(c => new { c.CategoryId, c.ColorId }) 
.Select(g => new 
{ 
    categoryId = g.Key.CategoryId, 
    colorId = g.Key.ColorId, 
    sumOfWeights = g.Sum(r => (decimal?)r.Weight) ?? 0, 
}).ToList(); 

var categoriesAndColors = dbContext.Categories.AsEnumerable() 
.SelectMany(category => dbContext.Colors.AsEnumerable() 
.Select(color => new 
{ 
    category = new 
    { 
     categoryId = category.CategoryId, 
     name = category.Name, 
    }, 
    color = new 
    { 
     colorId = color.ColorId, 
     name = color.Name, 
    }, 
    inputWeightsSum = boxesInputs.Where(r => r.categoryId == category.CategoryId && r.colorId == color.ColorId).Sum(r => (decimal?) r.sumOfWeights) ?? 0, 
    outputWeightsSum = boxesOutputs.Where(r => r.categoryId == category.CategoryId && r.colorId == color.ColorId).Sum(r => (decimal?)r.sumOfWeights) ?? 0, 
})).ToList(); 

在上面的代碼中,前兩個查詢返回的:

category.name color.name  inputWeightsSum 
------------------------------------------------------- 
    c    null    0 
    c    red    0 
    c    blue    0 
    m    null    0 
    m    red    0 
    m    blue    0 
          .... 

    category.name color.name  outputWeightsSum 
------------------------------------------------------- 
    c    null    0 
    c    red    0 
    c    blue    0 
    m    null    0 
    m    red    0 
    m    blue    0 
          .... 

,第三個加入這兩個。我想我需要改進這個連接,因爲我失去了空值。

另外,這段代碼使用內存中的代碼,我希望它是一個單一的sql查詢(linq-to-entities而不是linq-to-objects與linq-to-entities混合)。可能嗎?因爲BoxOutput和BoxInput是兩個不同的表格,它們不是直接相連的。不管怎樣,最終我最終會得到3個查詢?

+0

我想我需要一個羣組加入 – sports 2014-11-21 21:35:24

+0

你只是想得到一個笛卡爾產品? – paqogomez 2014-11-21 21:36:50

+0

我的代碼的前兩個查詢被授予是正確的..我只是想將這兩個合併爲一個結果,按「(類別,顏色)」 – sports 2014-11-21 21:44:22

回答

0

您從兩個表中選擇一個相同的匿名類型,將它們合併在一起,然後執行您的組並選擇。這樣的事情:

dbContext.BoxesInputs 
.Select(g => new TempClass 
{ 
    CategoryId = g.CategoryId, 
    ColorId = g.ColorId, 
    InputWeight = r.Weight, 
    OutputWeight = 0, 
}) 
.Union(dbContext.BoxesOutputs 
    .Select(g => new TempClass 
    { 
     CategoryId = g.CategoryId, 
     ColorId = g.ColorId, 
     InputWeight = 0, 
     OutputWeight = r.Weight 
    }) 
) 
.GroupBy(c => new { c.CategoryId, c.ColorId }) 
.Select(g => new 
{ 
    categoryId = g.Key.CategoryId, 
    colorId = g.Key.ColorId, 
    sumOfInputWeights = g.Sum(r => r.InputWeight), 
    sumOfOutputWeights = g.Sum(r => r.OutputWeight), 
}).ToList(); 

public class TempClass 
{ 
    public int CategoryID { get; set; } 
    public int ColorID { get; set; } 
    public decimal InnerWeight { get; set; } 
    public decimal OuterWeight { get; set; } 
} 
+0

分組但是然後我會得到只有一列「sumOfWeights」和我需要「inputsSumOfWeights」和「outputsSumOfWeights」,在相同結果內分離出 – sports 2014-11-21 21:43:10

+0

檢查我的編輯。這應該工作。不知道是否優化,但可能比將整個表拉入內存更好。 – DLeh 2014-11-21 21:46:11

+0

不錯的訣竅,我會測試它。 – sports 2014-11-21 21:50:36