2016-08-12 150 views
1

我有一張發票,它可以包含稱爲軌道的項目。 InvoiceLine是連接兩者的聯結表。如果發票至少包含一首曲目,則一切正常。我想要實現的是即使不包含曲目,也要退回發票。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

聽起來像你可以使用'左連接'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 for null too – superfly71

+0

這個答案實際上是錯誤的。在運行時你會得到着名的EF'NotSupportedException':「無法創建一個類型爲'Namespace.Track'的常量值,在這種情況下只支持原始類型或枚舉類型。」 –

+0

我已經使用此代碼的主要時間。這是實現左外連接的一種方式。鏈接 - 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 
... 

Left Outer Join的MSDN文檔。

+0

還要確保當你'左連接',當訪問一個左聯合表的屬性來檢查它不是空:'track?.SomeProperty' - 否則你會得到一個'NullReferenceException'的情況下真的沒有記錄 –

+0

使用默認值來避免'NullReferenceException' – Sathish

+0

@GiladGreen在LINQ to Entities中它確實沒關係--SQL從不生成NRE。唯一的要求是如果您有一個不可爲空的值類型屬性將其轉換爲可空。當然'對! - null? right.Prop:default_value'和類似的結構被支持。 –