3

我有 2 个模型:

public class User
{
    public int Id { get; set; }

    [Required] 
    [MaxLength(50)]
    public string Email { get; set; }

    [Required] 
    [MaxLength(100)] 
    public string Password { get; set; }
}

public class Questionnaire
{
    public int Id { get; set; }

    [Required] 
    [MaxLength(500)] 
    public string Title { get; set; }

    public User User { get; set; }
}

我想用这个查询来检索某个用户的所有问卷:

List<Questionnaire> questionnaires = this._dbContext.Questionnaires.Where(a => a.User.Id == 1).ToList();

它可以工作,但实体框架会产生这个 sql 查询:

SELECT `q`.`Id`, `q`.`Title`, `q`.`UserId`
FROM `Questionnaires` AS `q`
     LEFT JOIN `Users` AS `u` ON `q`.`UserId` = `u`.`Id`
WHERE `u`.`Id` = 1;

在我看来,左连接是不必要的。请问有什么解决方法可以避免这种左连接吗?先感谢您。

4

2 回答 2

2

您将需要手动公开UserId属性:Questionnaire

public class Questionnaire
{
    public int Id { get; set; }

    [Required] 
    [MaxLength(500)] 
    public string Title { get; set; }

    public int UserId { get; set; }
    public User User { get; set; }
}

并在查询中使用它而不是a.User.Id

var questionnaires = this._dbContext.Questionnaires
    .Where(a => a.UserId == 1) // use UserId instead of User.Id
    .ToList(); 
于 2021-01-18T19:54:44.720 回答
1

了解更多信息:

如果您选择不在关系的依赖端显式包含外键属性,EF Core 将使用模式 Id 创建一个影子属性。如果您查看Questionnaire数据库表,UserId列存在并且它已由 EF 核心创建为影子外键。

当您User在 where 子句中引用时_dbContext.Questionnaires.Where(a => a.User.Id == 1),EF Core 会将 linq 查询转换为 TSQL 左连接。

您还可以使用影子属性来定义外键:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<Questionnaire>()
        .Property<int>("UserId");

    builder.Entity<Questionnaire>()
        .HasOne(e => e.User)
        .WithMany()
        .HasForeignKey("UserId")
        .OnDelete(DeleteBehavior.SetNull);
}

现在左连接将替换为内连接:

SELECT [q].[Id], [q].[Title], [q].[UserId]
      FROM [Questionnaires] AS [q]
      INNER JOIN [Users] AS [c] ON [q].[UserId] = [c].[Id]
      WHERE [c].[Id] = 1

为避免不必要的加入,正如@Guru Stron 所说,您需要在课堂上公开UserId属性。Questionnaire

于 2021-01-18T21:08:27.023 回答