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

时间:2016-10-26 14:52:52

标签: c# entity-framework linq

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

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

这是模型:

Person has a Student
Person has a car

所以两次(因为我的人只有学生)包括(错误地)学生,​​是否有问题?
附:我只希望它包含在内!因为我只有一个学生。 ef会抱怨这个吗?我尝试了它似乎没问题,但我不知道这个含义。任何人都可以解释/详述吗?搜索了一下,但无法确定任何问题。

4 个答案:

答案 0 :(得分:4)

拿这个样本:

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]

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

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也足够智能生成相同的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();

重复包含和多次。这是生成的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]

再次使用相同的代码。所以,是的。我们可以说它会好的,虽然有点奇怪的事情要做。

希望这有帮助!

答案 1 :(得分:2)

如果您调用两次,则会生成相同的查询。结果相同,就像这样

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]

答案 2 :(得分:1)

这完全有效,无论如何都不会绊倒EF。考虑如何包含挂起像Student之类的引用的其他引用和集合。你可以像这样写它们。您提出的建议不会比以下示例更加混淆EF。

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

答案 3 :(得分:1)

对于EF 6

使用System.Data.Entity;

query.Include(x => x.Collection.Select(y => y.Property))

确保使用System.Data.Entity添加;以获得包含lambda的Include版本。

对于EF Core

使用新方法ThenInclude

query.Include(x => x.Collection)
     .ThenInclude(x => x.Property);