Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behaviour when including the same field twice in entity framework linq

what happens when I include the same field twice, meaningly I take from db an entity and I use the EF .include option. What I mean is this:
I have:

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

This is the model:

Person has a Student
Person has a car

so by including (by mistake) the student twice (since my person has ONLY a student), is there an issue?
P.S. I only want it included ONCE! since I have only a single student. Does ef complain about this? I tried it and it seemed ok, but I do not know the implications of this. Can anyone explain/elaborate? Searched a bit but couldn't identify any issues.

like image 922
first last Avatar asked Oct 26 '16 14:10

first last


2 Answers

Take this sample:

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; }
}

A rent contains the Student and the Car.

Lets make a query with unique Include clauses:

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

This is the generated 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]

Let's make a query duplicating an Include:

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

You'll get this 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]

As you can see, EF is smart enough to generate the same sql even when you specify an Include more than once.

UPDATE: Repeated includes (many times)

Let's try this:

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 Includes and several times. And here's the generated 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]

Just the same code again. So, yes. We could say it'll be ok, although a little weird thing to do.

Hope this helps!

like image 169
Karel Tamayo Avatar answered Nov 14 '22 23:11

Karel Tamayo


If you call it twice, the same query will be generated. Result the same, something like this

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]
like image 23
Grigor Aleksanyan Avatar answered Nov 14 '22 22:11

Grigor Aleksanyan