【问题标题】:How do I join with OR condition?如何加入 OR 条件?
【发布时间】:2013-05-21 18:29:28
【问题描述】:

这是我的 LINQ 代码:

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 to Entities 翻译:

    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)

谁能告诉我为什么或我做错了什么?

更新 这是我的模型的简化版本:

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; }

}

【问题讨论】:

  • 这两个表中有哪些外键?
  • 我刚刚添加了一个更新,包括我的模型,您可以在其中查看 FK 关系

标签: c# entity-framework join linq-to-entities ef-code-first


【解决方案1】:

从 EF LINQ 中获取 SQL 是一个多步骤的过程,因此并不总是很容易看到某些操作在哪里转换。 LINQ 创建一个与语言无关的表达式树,它被传递到 EF 运行时。 EF 然后创建一个“规范的”查询表达式树。这样做的原因是 EF 可以在场景下使用许多不同的 DB ADO 提供程序之一,所以此时,它只是获得了可以在数据库上使用的通用表达式树。然后,它将这个“规范”查询表达式传递给 EF ADO 提供程序,然后由它生成实际的 SQL 语句。

在其中一次通过期间,您的 OR 条件被“优化”了,我怀疑它与 LINQ 处理连接的方式有关。在您的情况下,如果 LINQ 语句中没有实际的 JOIN 子句,我怀疑默认情况下会执行内部联接,从技术上讲,该联接的一侧不能使用 NULL(联接的两侧必须在内部联接中匹配)。

您真正想要的是留下 OUTER JOIN,其中允许一侧有 NULL。如果您在 Internet 上查询 LINQ 和 OUTER JOIN,您将获得一些示例,说明如何创建 LINQ 语句,从而允许其中一侧包含 NULL。

【讨论】:

    【解决方案2】:

    是否有可能拥有 AUXComponentTypes.ComponentCategoryCode == null?该字段是否标记为不可为空?

    【讨论】:

    • 对!该属性被标记为必需(请参阅上面的模型)并且与可以为空的 db 定义不匹配。非常感谢
    猜你喜欢
    • 2020-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    相关资源
    最近更新 更多