在实体框架linq中两次包含相同字段时的行为

本文关键字:字段 包含相 两次 linq 框架 实体 | 更新日期: 2023-09-27 18:14:58

当我包含相同的字段两次时会发生什么,这意味着我从数据库中获取一个实体,我使用EF .include选项。我的意思是:
我有:

.Include(x => x.Student)
.Include(x => x.Car)
.Include(x => x.Student)

这是模型:

Person has a Student
Person has a car

所以通过(错误地)包含学生两次(因为我的人只有一个学生),有问题吗?
附言:我只希望它包含一次!因为我只有一个学生。他对此有抱怨吗?我试了一下,似乎还行,但我不知道这意味着什么。有人能解释一下吗?搜索了一下,但没有发现任何问题。

在实体框架linq中两次包含相同字段时的行为

举个例子:

public class RentContext : DbContext
{
    public DbSet<Student> Students { get; set; }
    public DbSet<Rent> Rents { get; set; }
    public DbSet<Car> Cars { get; set; }
}
public class Car
{
    public int Id { get; set; }
    public string Model { get; set; }
    public double Price { get; set; }
}
public class Rent
{
    public int Id { get; set; }
    public Student Student { get; set; }
    public Car Car { get; set; }
}
public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Year { get; set; }
}

租金包含学生和汽车。

让我们用唯一的Include子句创建一个查询:

var rents = ctx.Rents
    .Include(x => x.Student)
    .Include(x => x.Car)
    //.Include(x => x.Student)
    .ToList();

生成的sql:

SELECT
[Extent1].[Id] AS [Id],
[Extent2].[Id] AS [Id1],
[Extent2].[Name] AS [Name],
[Extent2].[Year] AS [Year],
[Extent3].[Id] AS [Id2],
[Extent3].[Model] AS [Model],
[Extent3].[Price] AS [Price]
FROM   [dbo].[Rents] AS [Extent1]
LEFT OUTER JOIN [dbo].[Students] AS [Extent2] ON [Extent1].[Student_Id] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Cars] AS [Extent3] ON [Extent1].[Car_Id] = [Extent3].[Id]

让我们创建一个复制Include的查询:

var rents = ctx.Rents
    .Include(x => x.Student)
    .Include(x => x.Car)
    .Include(x => x.Student)
    .ToList();
你会得到这样的sql:
SELECT
[Extent1].[Id] AS [Id],
[Extent2].[Id] AS [Id1],
[Extent2].[Name] AS [Name],
[Extent2].[Year] AS [Year],
[Extent3].[Id] AS [Id2],
[Extent3].[Model] AS [Model],
[Extent3].[Price] AS [Price]
FROM   [dbo].[Rents] AS [Extent1]
LEFT OUTER JOIN [dbo].[Students] AS [Extent2] ON [Extent1].[Student_Id] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Cars] AS [Extent3] ON [Extent1].[Car_Id] = [Extent3].[Id]

正如您所看到的,EF足够聪明,即使您多次指定Include也能生成相同的sql。

更新:重复包含(多次)

让我们试试这个:

var rents = ctx.Rents
    .Include(x => x.Student)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Car)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .Include(x => x.Student)
    .ToList();

Repeated包括和多次。下面是生成的sql:

SELECT
    [Extent1].[Id] AS [Id],
    [Extent2].[Id] AS [Id1],
    [Extent2].[Name] AS [Name],
    [Extent2].[Year] AS [Year],
    [Extent3].[Id] AS [Id2],
    [Extent3].[Model] AS [Model],
    [Extent3].[Price] AS [Price]
    FROM   [dbo].[Rents] AS [Extent1]
    LEFT OUTER JOIN [dbo].[Students] AS [Extent2] ON [Extent1].[Student_Id] = [Extent2].[Id]
    LEFT OUTER JOIN [dbo].[Cars] AS [Extent3] ON [Extent1].[Car_Id] = [Extent3].[Id]

还是同样的代码。所以,是的。我们可以说它会没事的,尽管这样做有点奇怪。

希望这对你有帮助!

如果调用两次,将生成相同的查询。结果相同,像这样

SELECT
    [Extent1].[Id] AS [Id],
    [Extent1].[Title] AS [Title],
    [Extent1].[PersonId] AS [PersonId],
    [Extent2].[Id] AS [Id1],
    [Extent2].[Name] AS [Name]
    FROM  [dbo].[Books] AS [Extent1]
    INNER JOIN [dbo].[People] AS [Extent2] ON [Extent1].[PersonId] = [Extent2].[Id]

这是完全有效的,无论如何都不会使EF出错。考虑如何包含挂起引用(如Student)的附加引用和集合。你可以这样写。你的建议不会比下面的例子更让EF感到困惑。

.Include(x => x.Student.Teacher)
.Include(x => x.Car)
.Include(x => x.Student.DrivingLog)