I am having an issue getting the records I need from 1 query using the include extension.
This is what is mostly working:
_db.Companies.Where(x => x.CompanyID == id)
.Include(x => x.Contact)
.Include(x => x.Properties.Select(p => p.Contact))
.Include(x => x.Properties.Select(f => f.Facilities.Select(c => c.Contact)))
.Include(x => x.Properties.Select( => f.Facilities.Select(s => s.Sections.Select(si => si.SectionIdeas))))
.SingleOrDefault();
This is fine except entity initiates a separate query for each license since I am not including it.
Since I would like to get the license in the same query I tried this:
_db.Companies.Where(x => x.CompanyID == id)
.Include(x => x.Contact)
.Include(x => x.Properties.Select(p => p.Contact))
.Include(x => x.Properties.Select(f => f.Facilities.Select(c => c.Contact)))
.Include(x => x.Properties.Select(f => f.Facilities.Select(l => l.Licenses)))//added
.Include(x => x.Properties.Select(f => f.Facilities.Select(s => s.Sections.Select(si => si.SectionIdeas))))
.SingleOrDefault();
This causes another row to be returned for each facility. Is there a way to get the license without additional rows?
Related
I am loading a customer and its related entities using the following (this is .NET Core 3.1 and Entity Framework Core).
var customer = loyaltyContext.Customer
.Include(c => c.ContactInformation)
.Include(c => c.Address)
.Include(c => c.MarketingPreferences)
.Include(c => c.ContentTypePreferences)
.Include(c => c.ExternalCards)
.Where(c => c.CustomerInternalId == customerInternalId).First();
However, a customer can have more than one ExternalCard, but only one card will be 'ACTIVE', so in pseudo code, what I'd really like to do is:
var customer = loyaltyContext.Customer
.Include(c => c.ContactInformation)
.Include(c => c.Address)
.Include(c => c.MarketingPreferences)
.Include(c => c.ContentTypePreferences)
.Include(c => c.ExternalCards WHERE CardStatus == "ACTIVE")
.Where(c => c.CustomerInternalId == customerInternalId).First();
So I don't return the last 10 cards the customer had (but which are now inactive). Is this possible in any way using EF Core? I can't seem to find the right syntax for this. At least not without having to create additional queries (whereas I'd rather just bring back less data to begin with).
ExternalCards is an ICollection< ExternalCards > as one customer can have many cards.
Filtering include option is not available in EF Core version <= 3.1. It's a new feature in EF Core 5.0. Here it is for EF Core 5.0 : Filtered Include
For EF Core <=3.1, You have to do the filtering in memory as follows:
var customer = loyaltyContext.Customer
.Include(c => c.ContactInformation)
.Include(c => c.Address)
.Include(c => c.MarketingPreferences)
.Include(c => c.ContentTypePreferences)
.Include(c => c.ExternalCards)
.Where(c => c.CustomerInternalId == customerInternalId).First();
customer.ExternalCards = customer.ExternalCards.Where(ec => ec.CardStatus == "ACTIVE").ToList();
This question already has an answer here:
EF Core Include on multiple sub-level collections
(1 answer)
Closed 3 years ago.
I am trying to query an entity with multiple levels of collections, and multiple collections at a single level. I'm using Include() and ThenInclude(), but not having much success. The examples I find don't have multiple collections on the same level and I haven't had any luck applying the technique to my use case.
This is a simplified illustration of my entities. Those with the [] are collections:
Home
Areas[]
Area
Name
Categories[]
Name
Recommendations[]
Subcategories[]
Name
Recommendations[]
Area
Name
Categories[]
Name
Recommendations[]
Subcategories[]
Name
Recommendations[]
I've gotten this far:
result = Home
.Include(x => x.Areas)
.ThenInclude(a => a.Categories)
.ThenInclude(c => c.Subcategories)
.ThenInclude(s => s.Recommendations)
However, this misses the Categories[].Recommendations[] collection. It's because there are two collections at the same level (Recommendations[] and Subcategories[]).
Any suggestions for a way to structure this query so I can get the desired result?
Thanks.
You have to call Include for each level:
result = Home
.Include(x => x.Areas)
.ThenInclude(a => a.Categories)
.ThenInclude(c => c.Subcategories)
.ThenInclude(s => s.Recommendations)
.Include(x => x.Areas)
.ThenInclude(a => a.Recommendations)
You have to write your query as follows:
result = Home
.Include(x => x.Areas)
.ThenInclude(a => a.Categories)
.ThenInclude(s => s.Recommendations)
.Include(x => x.Areas)
.ThenInclude(c => c.Subcategories)
I want to get all layergroups and include (eager loading) layers that have a specific url.
Here are my tables:
- LayerGroup (id, List<Layer>layers and more...)
- Layer(id, url, List<Attribute>attributes and more...)
- Attribute (id and more...)
This is what i got so far.
var groups = _context.LayerGroups
.Where(group => group.IsActive)
.Where(g => g.Layers.All(l => l.IsActive == true))
.Where(g => g.Layers.All(l => l.Url == "example1"))
.Include(g => g.Layers)
.ThenInclude(layer => layer.Attributes)
.Include(group => group.Layers).ThenInclude(layer => layer.SearchEngines)
.ToList();
But it seems to only get groups if exactly all layers is active and have the url example1. I want to get the layers with the right Url, even if the groups have layers with other url:s.
According to this you cannot filter Include and ThenInclude collection but you can filter parent with the condition based on Include. If you need so then you can write your query as follows:
var groups = _context.LayerGroups.Where(group => group.IsActive)
.Include(g => g.Layers)
.ThenInclude(layer => layer.Attributes)
.Include(group => group.Layers)
.ThenInclude(layer => layer.SearchEngines)
.Where(g => g.Layers.Any(l => l.IsActive == true && l => l.Url == "example1"))
.ToList();
I have nested entities like Property -> Facility -> Farm -> License etc.
I want to get the most recent license and my original query looks like this.
return _db.Properties
.Include(c => c.Contact)
.Include(f => f.Facilities.Select(c => c.Contact))
.Include(f => f.Facilities.Select(ff => ff.Farms.Select(s => s.Species)))
.Include(x => x.Facilities.Select(l => l.Licenses))
.SingleOrDefault(x => x.PropertyID == id);
Since I want to get the most recent license I tried
return _db.Properties
.Include(c => c.Contact)
.Include(f => f.Facilities.Select(c => c.Contact))
.Include(f => f.Facilities.Select(ff => ff.Farms.Select(s => s.Species)))
.Include(x => x.Facilities.Select(l => l.Licenses.OrderByDescending(d => d.IssueDate)))
.SingleOrDefault(x => x.PropertyID == id);
which fails of course because you cant use an orderby clause there.
If I try an orderby clause at the end of the linq it will start at Property and I will need to drill down to the licenses again.
What is the preferred convention for this?
--EDIT--
Based on Robert's suggestion I flipped the query to get the Licenses first but I guess I need to do some projection since this query only gives me the Property entity and no child entities.
return _db.Licenses.OrderByDescending(x => x.IssueDate)
.Include(f => f.Facility)
.Include(f => f.Facility.Property)
.Include(f => f.Facility.Property.Contact)
.Include(c => c.Facility.Contact)
.Include(f => f.Facility.Farms)
.Include(f => f.Facility.Farms.Select(s => s.Species))
.Where(x => x.Facility.Property.PropertyID == id)
.Select(x => x.Facility.Property).SingleOrDefault();
Any ideas to get all children?
I'm trying to do an include of a nested entity. I assumed the below code would work but it does not recognize the CapitalMailOrders entitycollection. Can anyone point me in the right direction to include these?
var result = db.Contacts
.Include(a => a.IDXPageLinks)
.Include(b => b.ReboGatewayLoginInfoes)
.Include(c => c.SocialMedias)
.Include(d => d.WebSiteInfoes)
.Include(e => e.ContactImages)
.Include(f => f.RealtorSetUpProcesses)
.Include(h => h.RealtorSetUpProcesses.CapitalMailOrders) // getting compile time error here. Doesn't recognize Entity
.Include(g => g.Contact_CarrierCode_Assignments)
.FirstOrDefault(c => c.ContactID == id);
Thanks
The extra entity level is accessed from a collection and so you need to add a Select in order to bring all the entries into the include.
.Include(h => h.RealtorSetUpProcesses.Select(h2 => h2.CapitalMailOrders)