EF Core Including multiple levels issue - c#

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.

Related

Use multiple include and then include in EF query C#

I tried this code:
var result = _repository.Entity
.Include(x => x.table1)
.Include(x => x.table2).ThenInclude(x => x.table3).ThenInclude(x => x.table4)
.Where(x => x.table1.Id == 10)
I want to achieve like below which is not working:
var result = _repository.Entity
.Include(x => x.table1).select(new table1{..})
.Include(x => x.table2).ThenInclude(x => x.table3).ThenInclude(x => x.table4)
.Where(x => x.table1.Id == 10)
In this query, I want to use select on table1 i.e. to select on few columns say id, name.
I am trying but I use select right after the .Include(x => x.table1).select(....) then I am unable to use .Include for other tables.
I am not sure how to achieve this with join conditions; I tried but not able to achieve this, a small idea to resolve this will be helpful to proceed further.

join table to table related to the parent table

Still new to LINQ so be nice.
This query:
var query = _ODSContext.AllFacilities
.Where(f => f.AllFacilityContacts.Any(c => ProviderContactIds.Contains(c.ContactID) &&
(c.ContactTypeName == "Primary Rep")))
.Where(f => f.TermDate > DateTime.Now)
.Include(a => a.Address)
.Include(b => b.AllFacilityContacts)
.Include(c => c.AllPractitionerLocations)
.Include(e => e.AllFacilityServices)
.OrderBy(f => f.FacilityName);
works fine.
However, I want to add a table that joins to AllpractitionerLocations:
Here's what I tried:
var query = _ODSContext.AllFacilities
.Where(f => f.AllFacilityContacts.Any(c => ProviderContactIds.Contains(c.ContactID) &&
(c.ContactTypeName == "Primary Rep")))
.Where(f => f.TermDate > DateTime.Now)
.Include(a => a.Address)
.Include(b => b.AllFacilityContacts)
.Include(c => c.AllPractitionerLocations)
.Include(d => d.AllPractitionerNetworkSpecialty)
.Include(e => e.AllFacilityServices)
.OrderBy(f => f.FacilityName);
But I get:
'AllFacility' does not contain a definition for
'AllPractitionerNetworkSpecialties' and no accessible extension method
'AllPractitionerNetworkSpecialties' accepting a first argument of type
'AllFacility' could be found (are you missing a using directive or an assembly reference?
Which is technically accurate. AllPractitionerNetworkSpecialties is related to AllPractitionerLocations.
How do I do the join between those two tables in LINQ?
Thanks,
You use ThenInclude
Simplistically, Include starts off from the root entity, ThenInclude carries on from the entity type that you call it on. If you conceive your graph as a hub-spoke type affair with AllFacilities as the hub, your Include starts another spoke from the hub, whereas ThenInclude continues an existing spoke. If a customer has orders and orders have products, you'd context.Customer.Include(... Orders).ThenInclude(... Products). If you wanted to "go back to the hub" and get the Customer>Address>Country>TaxYearCodings you'd
context.Customer
.Include(... Orders)
.ThenInclude(... Products)
.Include(... Address)
.ThenInclude(... Country)
.ThenInclude(... TaxYearCodings)
We (at work) tend to indent another level when we ThenInclude to signify "continuing a spoke", and indent all the Includes the same to signify "going back to the hub".
Possibly also worth pointing out that you can chain your Include and ThenInclude by accessing the chain "in a one-er" but you can't navigate into collections, only single props - you start another inclusion when you hit a collection
customer.Include(c => c.Address.Country.TaxYearCodings).ThenInclude(tyc => ...)
Be careful; the amount of data you load when you start (then)including a lot can be enormous

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, Any could not be translated and will be evaluated locally

I have procedure which returns me entity's ids which I need.
(I decide to create this procedure, because entities which should be returned to the end user, are filtered by related entities, but EF Core does not support filtering by related entities).
Then I want to use this ids to get entities I need witch theirs related entities.
I'm using the Any operator. In my opinion it should generate query like this: WHERE id IN(1,2,3,4....)` but it seems it does not work like I want.
Instead, it returns warning with the information that the:
Any clause could not be translated and will be evaluated locally
How I could fix it?
My code below:
var assocsIds = await _context.Assoc.AsNoTracking()
.FromSql($"exec {SqlProcedures.GetAssocsForIndexProc} {query.IndexMviId}, {query.FilterByGroupId}")
.ToListAsync()
var productAssocs = await _context.Assoc
.Where(x => assocsIds.Any(z => z.Id == x.Id))
.Include(x => x.Attribute)
.ThenInclude(x => x.Translation)
.Include(x => x.Option)
.ThenInclude(x => x.Translation)
.Include(x => x.Mvi)
.ThenInclude(x => x.Translation)
.AsNoTracking()
.ToListAsync()
;
Can you first select "Id"s from assocsIds into another variable and then try the following?
var productAssocs = await _context.Assoc
.Where(x => yourIdsList.Contains(x.Id))
.Include(x => x.Attribute)
.ThenInclude(x => x.Translation)
.Include(x => x.Option)
.ThenInclude(x => x.Translation)
.Include(x => x.Mvi)
.ThenInclude(x => x.Translation)
.AsNoTracking()
.ToListAsync();

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