2016-08-12 9 views
1

私は請求書を持っており、トラックと呼ばれる項目を含めることができます。 InvoiceLineは、2つを接続するジャンクション・テーブルです。請求書に少なくとも1つのトラックが含まれている場合は、すべて正常に動作します。私が達成したいのは、トラックが含まれていなくても請求書を返すことです。請求書に商品が含まれていない場合、Linqはnullを返します

私の最初のコード:

var screenset = 
from inv in context.Invoices where inv.InvoiceId == invoiceID 
join line in context.InvoiceLines on inv.InvoiceId equals line.InvoiceId 
join track in context.Tracks on line.TrackId equals track.TrackId 
select new InvoiceAndItemsDTO 
{ 
    InvoiceId = inv.InvoiceId, 
    InvoiceDate = inv.InvoiceDate, 
    InvoiceTotal = inv.Total, 
    CustomerId = inv.CustomerId, 
    CustomerFullName = inv.Customer.LastName + ", " + inv.Customer.FirstName, 
    CustomerPhoneNumber = inv.Customer.Phone, 
    InvoiceLineId = line.InvoiceLineId, 
    TrackId = track.TrackId, 
    TrackName = track.Name, 
    TrackPrice = track.UnitPrice, 
    Artist = track.Album.Artist.Name, 
    UnitPrice = line.UnitPrice, 
    Quantity = line.Quantity, 
    Action = "None" 
}; 

は、上記の請求書を返し、それが任意のトラックが含まれている場合、正しく追跡します。

Invoice contains at least one track

基本的に上記のコードは、内側に何トラックが存在しない場合、結果セットが空になりそう参加あります。そこで、トラックがない場合でも請求書を含めるようにコードを修正しました。

var screenset = 
from inv in context.Invoices where inv.InvoiceId == invoiceID 
from j in context.Invoices where j.InvoiceId == invoiceID 
join line in context.InvoiceLines on j.InvoiceId equals line.InvoiceId 
join track in context.Tracks on line.TrackId equals track.TrackId 
select new InvoiceAndItemsDTO 
{ 
    InvoiceId = inv.InvoiceId, 
    InvoiceDate = inv.InvoiceDate, 
    InvoiceTotal = inv.Total, 
    CustomerId = inv.CustomerId, 
    CustomerFullName = inv.Customer.LastName + ", " + inv.Customer.FirstName, 
    CustomerPhoneNumber = inv.Customer.Phone, 
    InvoiceLineId = line.InvoiceLineId, 
    TrackId = track.TrackId, 
    TrackName = track.Name, 
    TrackPrice = track.UnitPrice, 
    Artist = track.Album.Artist.Name, 
    UnitPrice = line.UnitPrice, 
    Quantity = line.Quantity, 
    Action = "None" 
}; 

しかし、私は空の結果を得る:

Empty result

を私はjoin into newsetを使用してfrom e in newset.DefaultIfEmpty()を使用してみましたが、私は3つのテーブルを結合していますし、join intoは、最後のテーブルを作成し、すべての結合されたテーブルを含めることはできません。

私はこれに関する助けに感謝します。

ありがとうございます。

+0

InvoiceLinesクラスに 'Track'ナビゲーションプロパティが定義されていますか? – CodeNotFound

+1

「Left Join」のようなサウンドhttps://msdn.microsoft.com/tr-tr/vstudio/ee908647.aspx#leftouterjoin – uTeisT

+0

@CodeNotFound、はい私はInvoiceLinesのトラックナビゲーションプロパティを持っています – superfly71

答えて

1

左外部結合を使用して、トラックモデルのデフォルト値を指定できます。

Track defaultTrack= new Track() 
     { 
      TrackId = 0, 
      TrackName = "No Track", 
      TrackPrice = 0, 
      Artist = "No Artist", 
     }; 

//Left outer join 
var screenset = 
from inv in context.Invoices where inv.InvoiceId == invoiceID 
from j in context.Invoices where j.InvoiceId == invoiceID 
join line in context.InvoiceLines on j.InvoiceId equals line.InvoiceId 
join track in context.Tracks on line.TrackId equals track.TrackId into trackGroup 
from trackDetails in trackGroup.DefaultIfEmpty(defaultTrack) 
select new InvoiceAndItemsDTO 
{ 
    InvoiceId = inv.InvoiceId, 
    InvoiceDate = inv.InvoiceDate, 
    InvoiceTotal = inv.Total, 
    CustomerId = inv.CustomerId, 
    CustomerFullName = inv.Customer.LastName + ", " + inv.Customer.FirstName, 
    CustomerPhoneNumber = inv.Customer.Phone, 
    InvoiceLineId = line.InvoiceLineId, 
    TrackId = trackDetails .TrackId, 
    TrackName = trackDetails .Name, 
    TrackPrice = trackDetails .UnitPrice, 
    Artist = trackDetails .Album.Artist.Name, 
    UnitPrice = line.UnitPrice, 
    Quantity = line.Quantity, 
    Action = "None" 
}; 
+0

良い答えをありがとう!私はInvoiceLinesもヌルにチェックしなければならないと思う。 – superfly71

+0

この答えは実際には間違っている。実行時には、有名なEF 'NotSupportedException'が発生します:"型 'Namespace.Track'の定数値を作成できません。このコンテキストでは、プリミティブ型または列挙型のみがサポートされています。 –

+0

私はこのコードをメインタイムで使用しました。これは、左外部結合を達成する方法の1つです.Link - https://msdn.microsoft.com/tr-tr/vstudio/ee908647.aspx#leftouterjoin – Sathish

3

これは簡単です。

は、内部結合生成

from inv in context.Invoices where inv.InvoiceId == invoiceID 
join line in context.InvoiceLines on inv.InvoiceId equals line.InvoiceId 
join track in context.Tracks on line.TrackId equals track.TrackId 
... 

元のクエリを見てみましょう。

from inv in context.Invoices where inv.InvoiceId == invoiceID 
join line in context.InvoiceLines on inv.InvoiceId equals line.InvoiceId 
into lines from line in lines.DefaultIfEmpty() // turn the above to left join 
join track in context.Tracks on line.TrackId equals track.TrackId 
into tracks from track in tracks.DefaultIfEmpty() // turn the above to left join 
... 

は、MSDNのドキュメントでLeft Outer Joinを参照してください:左外部結合に変えるためには、あなたが必要とするすべては、2つの行を挿入することです。

+0

また、 'left join 'のときに、左ジョイントテーブルのプロパティにアクセスしてnullでないことを確認してください:' track?.SomeProperty' - それ以外の場合、それは 'NullReferenceException'を取得します実際にレコードがありませんでした –

+0

デフォルト値を使用して 'NullReferenceException'を避けてください – Sathish

+0

@GiladGreen LINQ to Entitiesでは、本当に重要ではありません.SQLは決してNREを生成しません。唯一の要件は、nullable型にキャストするためのnullable型の型のプロパティがある場合です。もちろん、そうです - ヌル? right.Prop:default_value'などの構文がサポートされています。 –

関連する問題