2013-05-21 30 views
4

這是我的LINQ代碼:如何加入OR條件?

from b in dbContext.SAPBillOfMaterials 
from t in dbContext.AUXComponentTypes 
where t.ParentId == b.Parent.Id && 
t.MaterialType == b.Component.MaterialType && 
(t.ComponentCategoryCode == null || t.ComponentCategoryCode == b.Component.ComponentCategoryCode) 
    select new 
    { 
     ComponentCode = b.Component.Model_ComponentCode, 
     Grid = b.Component.Grid , 
     ComponentType = t.ComponentType, 
     ConfigurationId = configId, 
     ParentSKUId = b.Parent.Id , 
     SKUId = b.Component.Id 
    }; 

這是LINQ到實體翻譯:

SELECT 
    [Extent2].[ParentId] AS [ParentId], 
    [Extent4].[Model_ComponentCode] AS [Model_ComponentCode], 
    [Extent4].[Grid] AS [Grid], 
    [Extent2].[ComponentType] AS [ComponentType], 
    [Extent1].[Parent_Id] AS [Parent_Id], 
    [Extent1].[Component_Id] AS [Component_Id] 
    FROM [dbo].[SAPBillOfMaterial] AS [Extent1] 
    INNER JOIN [dbo].[AUXComponentTypes] AS [Extent2] ON [Extent1].[Parent_Id] = [Extent2].[ParentId] 
    INNER JOIN [dbo].[SAPMasterMaterialSKU] AS [Extent3] ON ([Extent2].[MaterialType] = [Extent3].[MaterialType]) 
AND ([Extent1].[Component_Id] = [Extent3].[Id]) 
**AND ([Extent2].[ComponentCategoryCode] = [Extent3].[ComponentCategoryCode])** 
    LEFT OUTER JOIN [dbo].[SAPMasterMaterialSKU] AS [Extent4] ON [Extent1].[Component_Id] = [Extent4].[Id] 

所以,這是完全無視OR條件中加入:

(T .ComponentCategoryCode == null || t.ComponentCategoryCode == b.Component.ComponentCategoryCode)

有人能告訴我爲什麼或我做錯了什麼?

UPDATE 這裏的簡化版本我的模型:

public class AUXComponentType 
{ 
    [Key] 
    public int Id { get; set; } 

    [Required, ForeignKey("SAPMasterMaterialSKU")] 
    public int ParentId { get; set; } 

    public virtual SAPMasterMaterialSKU SAPMasterMaterialSKU { get; set; } 

    [Required,StringLength(4)] 
    public string MaterialType { get; set; } 

    [Required, StringLength(1)] 
    public string ComponentType { get; set; } 

    [Required, StringLength(20)] 
    public string ComponentCategoryCode { get; set; } 

} 

public class SAPBillOfMaterial 
{ 
    [Key, Column(Order = 1)] 
    public int Id { get; set; } 

    [InverseProperty("SAPBOMChilds"), Column(Order = 2)] 
    public virtual SAPMasterMaterialSKU Parent { get; set; } 

    [InverseProperty("SAPBOMs"), Column(Order = 3)] 
    public virtual SAPMasterMaterialSKU Component { get; set; } 

    public decimal Quantity { get; set; } 

} 

public class SAPMasterMaterialSKU 
{ 
    [Key] 
    public int Id { get; set; } 

    [Required,MaxLength(18)] 
    public string Model_ComponentCode { get; set; } 

    [MaxLength(8)] 
    public string Grid { get; set; } 

    [Required,MaxLength(4)] 
    public string MaterialType { get; set; } 


    [Required, MaxLength(20)] 
    public string ComponentCategoryCode { get; set; } 

    public virtual ICollection<SAPBillOfMaterial> SAPBOMChilds { get; set; } 
    public virtual ICollection<SAPBillOfMaterial> SAPBOMs { get; set; } 
    public virtual ICollection<AUXComponentType> AUXComponentTypes { get; set; } 

} 
+0

你在這兩個表中擁有哪些外鍵? – vittore

+0

我剛剛添加了一個更新,包括我的模型,您可以看到FK關係 –

回答

1

是否有可能有AUXComponentTypes.ComponentCategoryCode == null?該字段是否標記爲不可空?

+0

對!該屬性被標記爲必需(請參見上面的模型)並且不匹配db定義,該定義可以爲空。非常感謝 –

2

獲取SQL出EF LINQ的是一個多步驟的過程,所以它並不總是很容易看到某些操作得到轉化。 LINQ創建一個語言不可知的表達式樹,它被傳遞給EF運行時。 EF然後創建一個「cannonical」查詢表達式樹。原因是EF可以在場景中使用許多不同的DB ADO提供程序之一,因此在這一點上,它只是獲得可用於數據庫的通用樹表達式。然後它將這個「cannonical」查詢表達式傳遞給EF ADO Provider,後者又生成實際的SQL語句。

在這些過程中,你的OR條件被「優化」了,我懷疑它與LINQ如何處理連接有關。在你的情況下,LINQ語句中沒有實際的JOIN子句,我懷疑它默認情況下是做一個內部聯接,技術上它不能在NULL的連接的一端(聯接的兩端必須在內部聯接中匹配)。

你真正想要的是剩下的OUTER JOIN,其中一邊允許有NULL。如果你查詢LINQ和OUTER JOIN的互聯網,你將會得到一些關於如何創建LINQ語句的例子,其中一個邊允許包含NULL。