2010-12-04 11 views
1

のヘルプ私は、私が使用する必要がある3つのテーブルを持っている:
ワン系列
BrandID
名前
3つの表LINQクエリ

BrandSource-

のSourceID

ソース - をBrandID
SourceID
SourceName
イメージ

私はBrandSourceと私の中間テーブルを数多く持っています。各ブランドの列がテーブルに表示され、元のイメージの新しい列が作成されました。基本的に、1つのブランドについて5つのソースがある場合、ブランドの1つの行と私が作成した新しい列の5つの異なるソースイメージを表示する必要があります(1つのセルに5つの画像)。

私は3つのテーブルを結合しているので、BrandSourceテーブルに5行あり、各ブランドの5行がセル内に1つのソースイメージで表示されていることが明らかです。

私は別のブランドを選択することはできますが、それでも各ブランドのすべてのソース画像を同じセルに表示する方法についての問題は解決しません。

ここに私のlinqコードがあります。(ここには、簡潔さのために上に記した情報があります)。

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は、あなたのための詳細を処理できます。クエリのアスペクトを1秒遅らせて、望みの結果から始めれば、よりうまくいくでしょう。私が言うことから、あなたが望む目的のタイプはブランドのリストであり、各ブランドはそのソースのリストを含むべきです。ここでは、(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] 

そしてここではいくつかのテストデータは、自宅で一緒に、次の人のためだ。何であなたはブランドの#3のソースの空のリストにこの方法を取得することを

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 

お知らせ、私はあなたが望むと思う。元のクエリINNER JOINブランド#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

これは私が探していたものです。ありがとうございました。 –

0

は、新しいブランドであれば追跡するために変数を使用し、その後BrandID で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) + "..." }; 

そして、ここでは、私はそれを使用している方法です。

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

あなたは、このようにあなたの元のクエリにこのためGroupBy(またはクエリでgroup .. by .. into)を使用することができます。

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