Include same entity from multiple different entities - c#

I have a question about Include function in EF6.
I have multiple entities linked to a single entity for example:
SonA, SonB, SonC are all linked to FatherABC entity.
FatherABC has linked entities of his own: BrotherA, BrotherB, BrotherC
Now if I use include like this :
Son son = context.Sons.Where(x => ids.Contains(x => x.id))
.Include(x => x.Father)
.Include(x => x.Father.Brother)
.FirstOrDefault();
Will the include Father/Father.Brother work a single time for all of the entities? since it's the same entity?
Or will it query the data for each of the son entities?

Son son = context.Sons.Where(x => ids.Contains(x => x.id))
.Include(x => x.Father)
.ThenInclude(f => f.Brother)
.FirstOrDefault();
This should work

Related

How to include a table multiple times in Linq query

Here is my query, using EntityFramework 6.0
var x = context.Student
.Include(d => d.Class.Select(di => di.Teachers).Select(i => i.Subjects))
.Include(d => d.Class.Select(di => di.Teachers).Select(di => di.Marks))
.firstOrDefault();
Entities Subject and Class are childern of Teachers entity. How to include both the child entities in one query?
When the query is executed, does the Teachers entity will be loaded twice?
As the 'class' table is included twice, when the SQL is generated does it joins the 'class' table 2 times?
Are you using EF6 or EF Core? On EF Core you can use ThenInclude to load deeper level entities. Like (from MS Docs):
using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ThenInclude(author => author.Photo)
.Include(blog => blog.Owner)
.ThenInclude(owner => owner.Photo)
.ToList();
}

How to include multiple navigation properties of navigation property in EF6 in ASP.NET MVC with eager loading?

I have been trying to include multiple navigation properties of previously included navigation property, but I have not found correct syntax for it yet.
Entity relations are shown in the picture below:
Now, I want to load all the Cities, then all the Departments, then all the Employees and when I come to the Employee table I want to load Employee navigation properties: Projects (a collection of Project) as well as navigation properties Title and Country.
My code syntax is:
var model = dbContext.Cities.Include(c => c.Departments.Select(e => e.Employees.Select(p => p.Projects))).ToList();
In the code above the only Employee navigation property that is included is Projects (a list of Project, due to relation one to many). But how to include two other Employee navigation properties Title and Country?
You would need to more or less repeat your Include for each navigation property which you want loaded:
var model = dbContext.Cities
.Include(c => c.Departments) /* loads Departments */
.Include(c => c.Departments.Select(e => e.Employees)) /* loads Employees */
.Include(c => c.Departments.Select(e => e.Employees.Select(t => t.Title))) /* loads Title */
.Include(c => c.Departments.Select(e => e.Employees.Select(t => t.Country))) /* loads Country */
.Include(c => c.Departments.Select(e => e.Employees.Select(p => p.Projects))) /* loads Projects */
.ToList();
The syntax is a bit simpler in EF Core, using .ThenInclude, but I'm not aware of a simpler way to do this in .NET Framework.
Including, just so you've seen it, but won't work for EF6:
var model = dbContext.Cities
.Include(c => c.Departments)
.ThenInclude(c => c.Employees)
.ThenInclude(c => c.Title)
.Include(c => c.Departments)
.ThenInclude(c => c.Employees)
.ThenInclude(c => c.Country)
.Include(c => c.Departments)
.ThenInclude(c => c.Employees)
.ThenInclude(c => c.Projects)
.ToList();

EF Include sub level entities

I have this query:
var mapping = await context.MAPPING_COMPANIES
.Include(x => x.CUSTOMER_INFO)
.SingleOrDefaultAsync(where => where.AMIN_COMPANY_ID == aminCompanyId);
Now the single MAPPING_COMPANY will have a single CUSTOMER_INFO. I also need to include two more entities of CUSTOMER_INFO: MASTER_ADDRESS_TYPE and MASTER_CUSTOMER_STATUS. I need these two also included or flattened with the CUSTOMER_INFO.
How do I do that? I have experimented with more Including statements and combining Selects and even tried out the ThenIncludeBy.EF6 nuget but to no avail.
Have you tried this?
var mapping = await context.MAPPING_COMPANIES
.Include(x => x.CUSTOMER_INFO)
.Include(x => x.CUSTOMER_INFO.MASTER_ADDRESS_TYPE)
.Include(x => x.CUSTOMER_INFO.MASTER_CUSTOMER_STATUS)
.SingleOrDefaultAsync(where => where.AMIN_COMPANY_ID == aminCompanyId);
You'll need to make sure you do not have any Select(), or I think GroupBy(), in there since Include() only works if query shape matches the entity set.

EF Core Including multiple levels issue

With EF 6, I was querying like this and it was working nice.
IQueryable<Student> query = _testHelper.buildQuerty(id, userId)
.Include(x => x.Class)
.Include(x => x.Subjects)
.Include(x => x.Subjects.Select(y => y.Category));
Problem:
The same does not work in EF Core 2.0.
Error
System.ArgumentException occurred HResult=0x80070057 Message=The
property expression 'Subjects => {from Subjects y in Subjects select
[y].Category}' is not valid. The expression should represent a property
access: 't => t.MyProperty'. For more information on including
related data, see http://go.microsoft.com/fwlink/?LinkID=746393.
Opened up link, and refactored like this but it still not working and gives same error.
List<Student> query = _testHelper.buildQuerty(id, userId)
.Include(x => x.Class)
.Include(x => x.Subjects)
.ThenInclude(Subjects => Subjects.Select(y => y.Category)).tolist();
Where is the problem?
You're using the last chain of ThenInclude wrongly. You should use it like the code below.
List<Student> query = _testHelper.buildQuerty(id, userId)
.Include(x => x.Class)
.Include(x => x.Subjects)
.ThenInclude(subject => subject.Category);
With this ThenInclude extension method, you're dealing with an instance of Subject because of the last of use of Include which deal with a collection of that type.

Load EF entity with sibling includes

I have to load an entity from the database and I need to eagerly load into that entity almost all the relations from the database. I tried using Include but without success. Here is the code:
var thingy = _ctx.MASTERANDCOMMANDER
.Include(x => x.RED)
.Include(x => x.RED.Select(y => y.RED_ONE))
//.Include(x => x.RED.Select(y => y.RED_TWO))
.Include(x => x.GREEN)
.Include(x => x.GREEN.Select(y => y.GREEN_ONE))
.Include(x => x.GREEN.Select(y => y.GREEN_ONE.Select(z => z.GREEN_ONE_BIG)))
//.Include(x => x.GREEN.Select(y => y.GREEN_TWO))
//.Include(x => x.GREEN.Select(y => y.GREEN_THREE))
.SingleOrDefault(x => x.ID == "someId");
If I uncomment any of those includes, the app throws:
System.Exception: Oracle 11.2.0.2.0 doesn't support APPLY
Using EntityFramework 6 and Oracle 11.2.0.2.0.
I cannot upgrade EF nor Oracle.
How can I load the relations from GREEN_TWO, etc. into thingy?
Edit: All relations shown are one to many from left to right. Examples:
RED (1 to *) RED_ONE
GREEN_ONE (1 to *) GREEN_ONE_BIG
You can always use Join instead of Include, e. g.:
var thingy = _ctx.MASTERANDCOMMANDER
.Join(RED, x => x.MASTERANDCOMMANDERID, x => REDID, (m, r) => m)...etc...
and so on, where you need to get RED from your database as another single entity.
maybe using .ThenInclude() would help
var thingy = _ctx.MASTERANDCOMMANDER
.Include(x => x.RED)
.ThenInclude(red => red.RED_ONE)
.Include(x => x.GREEN)
.ThenInclude(green => green.GREEN_ONE)
.ThenInclude(greenOne => greenOne.GREEN_ONE_BIG)
.Where(x => x.ID == "someId").SingleOrDefault();

Categories