【问题标题】:My .Include statement doing INNER JOIN instead of LEFT JOIN (EF Core 3.1)我的 .Include 语句执行 INNER JOIN 而不是 LEFT JOIN (EF Core 3.1)
【发布时间】:2020-11-29 16:28:38
【问题描述】:

我已经看到基本上我需要使我的导航属性外键可以为空。我这样做了,但它仍然进行内部连接。

这是尝试加入组织的菜单表。请注意,MenuId 实际上与 Organizations 表中的 OrgId 值相同。

public partial class Menus
{
    [ForeignKey(nameof(Organizations))] 
    public int? MenuId { get; set; } //This is what I made nullable, but it still does an inner join
    public string MenuXml { get; set; }

    public Organizations Organizations { get; set; }
}

作为参考,这是我的组织模型的简化版本:

public partial class Organizations
{
    [Key]
    public int? OrgId { get; set; } //Also made this nullable, but I don't think I have to

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

    [Required]
    [MaxLength(70)]
    public string Name { get; set; }
}

这是我的 .Include 语句,我想成为左连接,但它正在执行内连接。组织表中有没有对应OrgId的MenuId记录:

var listForView = menus.AsNoTracking().Include(menus => menus.Organizations);

听起来很简单。 Google 和 SO 上的其他示例说,如果我将外键设为可为空的类型,它将是左连接,但它不会改变我的查询。

【问题讨论】:

  • 你是否遗漏了一些属性/流畅的配置?如果MenuId 是PK,即使您使用可空类型(主/备用键根据定义不可为空),它也不会被视为可空。此外,即使您以某种方式将其映射为可为空(如果它是键则不能),这也无法解决“在组织表中没有相应 OrgId 的菜单 ID 记录”,因为假设只有空值没有对应的记录,即期望是物理强制的关系数据库关系。
  • 感谢您的回复。所以,我想我知道数据库中有错误的数据(引用一行不存在的组织)。数据库不是我的,所以我无法控制。但是,我知道当我在 SQL 中编写 LEFT JOIN 时,我可以获得我想要的结果。 EF Core 中必须有一种方法可以做到这一点,不是吗?你说的有道理,我不能让表上的 Key 可以为空,所以 MenuId 不能为空。
  • 恐怕你不能在这种模式下使用 EF 自动加入服务,所以你必须求助于手动加入 - 我们不鼓励使用 EF,但这是唯一的方法。
  • 我可以接受这个答案。如果没有办法做到这一点,那就这样吧。我会想出一个解决方法。感谢您的帮助。

标签: sql asp.net-core entity-framework-core asp.net-core-3.1 ef-core-3.1


【解决方案1】:

您的代码对我来说运行得很好。生成的sql语句是leftjoin而不是innerjoin。我想知道您是否对配置有问题,这是我的代码: 菜单类:

public partial class Menus
    {

        [ForeignKey(nameof(Organizations))]
        public int? MenuId { get; set; } 
        public string MenuXml { get; set; }

        public Organizations Organizations { get; set; }

    }

组织类:

public partial class Organizations
{
    [Key]
    public int OrgId { get; set; }

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

    [Required]
    [MaxLength(70)]
    public string Name { get; set; }
}

你的上下文:

modelBuilder.Entity<Menus>().HasNoKey();

 public DbSet<Menus> Menus { get; set; }
 public DbSet<Organizations> Organizations { get; set; }

林克:

var listForView =context.Menus.AsNoTracking().Include(menus => menus.Organizations).ToList();

结果展示: enter image description here

【讨论】:

    猜你喜欢
    • 2021-09-29
    • 2021-06-25
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多