2010-12-04 35 views
1

我有3個表,我需要使用:
品牌 -
BrandID
名稱
用三個表LINQ查詢幫助

BrandSource-
BrandID
的SourceID

源 -
SourceID
來源地名稱
圖片

所以我與BrandSource有很多很多的關係是我的中間表。我在表格中顯示了每個品牌列,併爲源圖像​​創建了一個新列。從本質上講,如果一個品牌有5個來源,我需要它顯示品牌的一行以及我製作的新專欄中的5個不同的來源圖像(一個單元格中有5個圖像)。

由於我加入了這三個表格,它顯然看到BrandSource表格中有5行,並顯示單個源圖像在單元格中的每個品牌的5行。

我確定我可以選擇不同的品牌,但這仍然無法解決我如何讓每個品牌的所有源圖像都顯示在同一個單元格中的問題。

這是我的linq代碼:(正如你可以看到在這裏有一些信息,我忽略了上面的簡潔)。

var join = from b in db.Brands 
       join bs in db.Brands_Sources on b.BrandID equals bs.BrandID 
       join sb in db.Sources on bs.SourceID equals sb.SourceID 
       select new { Brand = b, source = sb.Image, c = b.Description.Length < 204 ? b.Description : b.Description.Substring(0, 204) + "..." }; 

這裏的是我如何使用它:

foreach (var result in join) 
    { 
     bool a = result.Brand.Active; 
     string chk = string.Empty; 
     if (a == true) 
      chk = "checked='checked'"; 
     else 
      chk = ""; 

      resultSpan.InnerHtml += "<tr><td><input type='checkbox' " + chk + "></td><td width='1%'><img width='50px' src='" + result.Brand.Image + "'</img></td>" + 
       "<td>" + result.Brand.Name + "</td><td width='60%'>" + result.c + "</td><td><img src='"+result.source+"'></img></td><td>" + result.Brand.DateCreated + "</td><td>" + result.Brand.DateModified + "</td></tr>"; 

    } 

回答

3

你有一個很好的開始,但我認爲你最好不要自己做三聯。 Linq-to-sql可以爲你處理這些細節。如果您退出查詢方面一秒鐘,然後從您想要的結果開始,您會做得更好。根據我所知道的,你想要的物品類型是品牌清單,每個品牌都應該包含其來源清單。這裏是你如何做到這一點(從下載LinqPad)...

// LinqPad C# statement(s) 
var results = 
from b in Brands 
select new { 
    Brand = b, 
    Sources = (
     from s in Sources 
     join xref in BrandSources on s.SourceID equals xref.SourceID 
     where xref.BrandID == b.BrandID 
     select s 
    ).ToList() 
}; 

result.Dump(); // show result in LinqPad 

LinqPad表明,這種執行一個查詢,但組裝的膽量你List<Source>在結果對象會在幕後。下面是LinqPad進行什麼活動:

SELECT [t0].[BrandID], [t0].[Name], [t1].[SourceID], [t1].[SourceName], [t1].[Image], (
    SELECT COUNT(*) 
    FROM [Source] AS [t3] 
    INNER JOIN [BrandSource] AS [t4] ON [t3].[SourceID] = [t4].[SourceID] 
    WHERE [t4].[BrandID] = [t0].[BrandID] 
    ) AS [value] 
FROM [Brand] AS [t0] 
LEFT OUTER JOIN ([Source] AS [t1] 
    INNER JOIN [BrandSource] AS [t2] ON [t1].[SourceID] = [t2].[SourceID]) ON [t2].[BrandID] = [t0].[BrandID] 

下面是一些測試數據對於那些在家裏沿着以下內容:

create table Brand (
BrandID int, 
Name varchar(50), 
) 

create table BrandSource (
BrandID int, 
SourceID int 
) 

create table Source (
SourceID int, 
SourceName varchar(50), 
[Image] varchar(50) 
) 

insert into Brand select 1, 'Brand1' 
insert into Brand select 2, 'Brand2' 
insert into Brand select 3, 'Brand3' 

insert into Source select 1, 'Source1', 'src1.gif' 
insert into Source select 2, 'Source2', 'src2.jpg' 
insert into Source select 3, 'Source3', 'src3.bmp' 
insert into Source select 4, 'Source4', 'src4.png' 
insert into Source select 5, 'Source5', 'src5.raw' 

insert into BrandSource select 1, 1 
insert into BrandSource select 1, 2 
insert into BrandSource select 1, 3 
insert into BrandSource select 2, 2 
insert into BrandSource select 2, 4 

select * from Brand 
select * from BrandSource 
select * from Source 

注意,你得到的源的空列表,對於品牌的#3這樣,這是什麼我假設你想要。您的原始查詢INNER JOIN ed品牌#3了。

最後,這裏有一個如何你會用你的查詢結果的一個例子:在你這樣原始查詢

foreach (var result in results) { 
    string chk = (result.Brand.Active ? " checked='checked'" : ""); 
    var buf = new StringBuilder(); 
    buf.Append("<tr>"); 
    buf.AppendFormat("<td><input type='checkbox'{0}></td>", chk); 
    buf.AppendFormat("<td width='1%'><img width='50px' src='{0}'></img></td>", result.Brand.Image); 
    buf.AppendFormat("<td>{0}</td>", result.Brand.Name); 
    buf.Append("<td>"); 

    foreach(var src in result.Sources) { 
     buf.AppendFormat("<img src='{0}'></img>", src.Image); 
    } 

    buf.Append("</td>"); 
    buf.Append("</tr>"); 

    resultSpan.InnerHtml = buf.ToString(); 

} 
+0

這正是我所期待的。謝謝。 – 2010-12-04 22:44:50

0

排序LINQ查詢通過BrandID 然後使用一個變量來跟蹤,如果它是一個新的品牌。

int lastBrandID = 0; 
string closeHtml = ""; 
foreach (var result in join) 
    { 
     if(result.Brand.BrandID != lastBrandID) 
     { 
      resultSpan.InnerHtml += closeHtml; 
      bool a = result.Brand.Active; 
      string chk = string.Empty; 
      if (a == true) 
       chk = "checked='checked'"; 
      else 
       chk = ""; 

      resultSpan.InnerHtml += "<tr><td><input type='checkbox' " + chk + "></td><td width='1%'><img width='50px' src='" + result.Brand.Image + "'</img></td>" + 
       "<td>" + result.Brand.Name + "</td><td width='60%'>" + result.c + "</td><td>"; 
      closeHtml = "</td><td>" + result.Brand.DateCreated + "</td><td>" + result.Brand.DateModified + "</td></tr>"; 
      lastBrandID = result.Brand.BrandID; 
     } 
     resultSpan.InnerHtml += "<img src='"+result.source+"'></img>"; 
    } 
    resultSpan.InnerHtml += closeHtml; 

在附註中,使用StringBuilder而不是連接字符串。 http://msdn.microsoft.com/en-us/library/2839d5h5%28v=VS.100%29.aspx

0

你可以(在查詢或group .. by .. into)使用GroupBy此:

var groups = join.GroupBy(b => b.Brand); 

foreach (var group in groups) 
{ 
    var brand = group.Key; 
    foreach (var row in group) 
    { 
     // you get the idea 
    } 

} 
-1
DataLoadOptions myOptions = new DataLoadOptions(); 
myOptions.LoadWith<Brand>(b => b.Brand_Sources); 
myOptions.LoadWith<Brand_Source>(bs => bs.Source); 

myDataContext.LoadOptions = myOptions; 


    // normally, some filtering is done, 
    // instead of reading the entire table. 
foreach(Brand brand in myDataContext.Brands) 
{ 
    List<Source> Sources = brand.Brand_Sources.Select(bs => bs.Source).ToList(); 

    // do stuff with brand and Sources 
} 
+0

只有在設置了EntitySets/Refs的情況下,這纔有效。在這種情況下,這可能是一個很好的選擇,因爲關係是經典的pk-> fk。 – mattmc3 2010-12-04 23:40:12