2009-08-30 4 views
1

テーブルAからすべてのフィールドを取得するLINQと、プロファイル1がテーブルABに値を持つフィールドを作成する助けを得ることができれば幸いです。プロファイル1にテーブルABにエントリがない場合は、値をnullとして表示します。LinqまたはSQLで次のように書くには

表プロファイルのために私が表示されます

AID Field 
----------- 
1  OneField 
2  TwoField 
3  ThreeField 

表B

BID Value 
----------- 
1  OneValue 
2  TwoValue 
3  ThreeValue 

表AB

ABID AID BID ProfileId 
------------------------- 
1  1  1 1 
2  2  3 1 

私はLINQの(またはSQLクエリ)を書き込むしようとしていますid 1、表aのすべての値、および適用される値は表bの値です。

ProfileID AID  Field  BID  Value 
-------------------------------------------------------- 
1   1   OneField  1   OneValue 
1   2   TwoField  3   ThreeValue 
1   3   ThreeField NULL  NULL 

プロファイル1が何を持っているそうでない場合は、目的は、テーブルAからのすべてのフィールドを取得することで、プロファイル1がテーブルABにエントリを持っているため、これらのフィールドは、テーブルBの値を表示し、見ないようにテーブルABのエントリは、次にヌルとして表示されます。

解決策が必要な場合は、SQLで記述し、ストアドプロシージャを使用して呼び出してください。これは動作するはず

おかげ

答えて

0

を私は完全な自己完結型のテストでの作業LINQソリューションを得ました。私は最後にアサーションを追加しませんでしたが、最後の変数 "queryResult"にはあなたが望む結果のリストが含まれています。私はそれをテストし、それが動作することを確認しました。ここでは、コードは次のようになります。

編集:あなたのコメントに応えてここでは、この

select TableA.*, TableB.* 
from TableA 
    left outer join TableC on TableA.ID = Aid 
    left outer join TableB on TableB.id = Bid 
where 
    TableC.ProfileID = 1 
    or TableC.ProfileID is null 

外側はあなたが結果を得る確実に参加するようにSQLのバージョンが見え例#2

public class tablea 
    { 
     public int AID { get; set; } 
     public string Field { get; set; } 
    } 
    public class tableb 
    { 
     public int BID { get; set; } 
     public string Value { get; set; } 
    } 
    public class tableab 
    { 
     public int ProfileID { get; set; } 
     public int AID { get; set; } 
     public string Field { get; set; } 
     public int BID { get; set; } 
     public string Value { get; set; } 
    } 

    public class result 
    { 
     public int? profileid { get; set; } 
     public int? aid { get; set; } 
     public string field { get; set; } 
     public string bid { get; set; } 
     public string value { get; set; } 
    } 

    [Test] 
    public void TestQuery() 
    { 
     var tablea = new List<tablea>(); 
     var tableb = new List<tableb>(); 
     var tableab = new List<tableab>(); 

     tablea.Add(new tablea{AID = 1,Field = "OneField"}); 
     tablea.Add(new tablea{AID = 2,Field = "TwoField"}); 
     tablea.Add(new tablea{AID = 3,Field = "ThreeField"}); 

     tableb.Add(new tableb{BID = 1,Value = "OneValue"}); 
     tableb.Add(new tableb{BID = 2,Value = "TwoValue"}); 
     tableb.Add(new tableb{BID = 3,Value = "ThreeValue"}); 

     tableab.Add(new tableab{AID = 1,BID=1,ProfileID = 1}); 
     tableab.Add(new tableab{AID = 2,BID=3,ProfileID = 1}); 

     var profileId = 1; 

     var q1 = (from a in tablea 
        let bid = (from ab in tableab where ab.ProfileID == profileId && ab.AID == a.AID select ab.BID).FirstOrDefault() 
        let value = (from ab in tableab where ab.ProfileID == profileId && ab.AID == a.AID && ab.BID == bid select ab.Value).FirstOrDefault() 
       select new result 
          { 
           profileid = profileId, 
           aid = a.AID, 
           field = a.Field, 
           bid = (bid == 0 ? "null" : bid.ToString()), 
           value = value ?? "null" 
          }).ToList(); 

    } 
+0

こんにちはRoberto。これをありがとう、それはユニットテストでかなり良い動作します。しかし、linq2sqlエンティティに対してDefaultIfEmptyは失敗します。なぜなら、空の場合はデフォルトで渡される値にfk constrainstがあり、例外 "System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException:操作がオブジェクトの現在の状態のため有効ではありません"が発生します。バマー。私は解決策を見つけたときに努力し続けます。ありがとう。 –

+0

ねえ...だから近い。残念ながら私はLINQ to SQLを使用していないので、制限があるのか​​分かりません。残念ながら、DefaultIfEmptyに対してnullを返すと、返されたオブジェクトのプロパティにアクセスしようとしているため、残りのクエリは失敗します。 – 7wp

+0

ありがとうRoberto。これは正しい方向に私を指摘している。私は努力し続けます。徹底的な答えとしてあなたのものをマークしてください。自己完結型の完全なテストを行うための+1。 –

0

(テストしていません):

SELECT ProfileID, A.AID, Field, B.BID, Value 
FROM AB 
LEFT OUTER JOIN A ON AB.AID = A.AID 
LEFT OUTER JOIN B ON AB.BID = B.BID 
+0

行3を戻しませんでした。これは私が立ち往生した場所です。 –

0

あなたがテーブルAからのすべての行をしたいので、あなたがテーブルAで開始する必要があります。

SELECT AB.ProfileID, A.AID, A.Field, B.BID, B.Value 
FROM A 
LEFT OUTER JOIN AB ON AB.AID = A.AID 
LEFT OUTER JOIN B ON AB.BID = B.BID 
WHERE (AB.ProfileID = 1 OR AB.ProfileID IS NULL) 

あなたの場合あなたのクエリでテーブルABから始めると、あなたはテーブルABにあるものだけを取得し、行3にはテーブルABにエントリがありません。

マルク

+0

ありがとうございましたmarc、しかしまだそれはかなりありません。なぜなら私がテーブルABに1つ以上のプロファイルを持ち、プロファイル2 AID = 3ならば、Bの左外部結合が機能しないからです。 ProfileID 1は2レコードを返し、profileid 2は3を返します。他のいくつかのプロファイルでAID = 3を使用すると、ProfileIDがnullにならないためレコードが失われていると思います。 –

+0

ここでの主な問題の1つは、profileIDを選択しようとしていますが、 "AB"結合テーブルで使用可能なもの以上のものを選択することです - それは本当に難しいです...... –

+0

「AB」テーブルにProfileIDを含めて選択する** ALL **行を追加し、「B」エンティティが関連付けられていない場合は「BID」列を空白のままにします。そうすれば、AB結合テーブルから選択し、 "ProfileID = x" WHERE句 –

0

でa.aidにABでABに参加から[コード] VAR結果= b.id上の(b)にBを結合するTMP2にab.bid等しいTMP1 にab.aid等しいですtmp1.DefaultIfEmpty(でCから )/ *これは、(tmp2.DefaultIfEmptyにおけるDからのNULL値*/ を得ることである)新しい {c.ProfileID、 a.AID、 a.Field、
を選択 c.bid、 d.Value }; [/コード]

0

以下の例を参照してください:

var result = from a in a 
      join ab in ab on a.aid equals ab.aid into tmp1 
     join b in b on b.id equals ab.bid into tmp2 
     from c in tmp1.DefaultIfEmpty() /* this is to get the null values */ 
     from d in tmp2.DefaultIfEmpty() 
     select new 
     { 
     c.ProfileID, 
     a.AID, 
     a.Field, 
       c.bid, 
     d.Value 
     }; 
+0

ありがとう!また、自分の投稿を編集して変更することもできます.2番目の投稿を追加したので、フォーマットされていないコードスニペットで最初のものを削除するのはなぜですか..... –

+0

Marcありがとう出てきましたが、削除ボタンが表示されません。恐れ入ります。 – Edwards

+0

こんにちは。Edwards、ありがとう。何らかの理由で、Visual Studioは、最初の結合の行に続く2番目の結合を好きではありません。何か不足していますか? –

0

です結合の反対側に一致するレコードがない場合でも、TableAから削除できます。結果としてProfileIDにもnull値を許可する必要があります。

関連する問題