Entity framework 在外键条件下产生左连接
Entity framework produces left join when condition on foreign key
我有 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();
有效,但 entity framework 生成此 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;
在我看来,左连接是不必要的。请问有什么解决方法可以避免这种左连接吗?提前谢谢你。
您需要在 Questionnaire
上手动公开 UserId
属性:
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();
更多信息:
If you choose not to explicitly include a foreign key property in the dependant end of the relationship, EF Core will create a shadow property using the pattern Id。如果您查看 Questionnaire
数据库 table,UserId
列存在并且它已由 EF 核心创建为影子外键。
当您在 where 子句 _dbContext.Questionnaires.Where(a => a.User.Id == 1)
中引用 User
时,EF Core 将 linq 查询转换为 TSQL 左连接。
你也可以使用 shadow 属性 定义外键:
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 所说,您需要在 Questionnaire
class.
上公开 UserId
属性
我有 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();
有效,但 entity framework 生成此 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;
在我看来,左连接是不必要的。请问有什么解决方法可以避免这种左连接吗?提前谢谢你。
您需要在 Questionnaire
上手动公开 UserId
属性:
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();
更多信息:
If you choose not to explicitly include a foreign key property in the dependant end of the relationship, EF Core will create a shadow property using the pattern Id。如果您查看 Questionnaire
数据库 table,UserId
列存在并且它已由 EF 核心创建为影子外键。
当您在 where 子句 _dbContext.Questionnaires.Where(a => a.User.Id == 1)
中引用 User
时,EF Core 将 linq 查询转换为 TSQL 左连接。
你也可以使用 shadow 属性 定义外键:
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 所说,您需要在 Questionnaire
class.
UserId
属性