How do I include a child of a child entitiy?
Ie, Jobs have Quotes which have QuoteItems
var job = db.Jobs
.Where(x => x.JobID == id)
.Include(x => x.Quotes)
.Include(x => x.Quotes.QuoteItems) // This doesn't work
.SingleOrDefault();
Just to be clearer - I'm trying to retrieve a single Job item, and it's associated Quotes (one to many) and for each Quote the associated QuoteItems (One Quote can have many QuoteItems)
The reason I'm asking is because in my Quote Index view I'm trying to show the Total of all the Quote items for each Quote by SUMming the Subtotal, but it's coming out as 0. I'm calling the Subtotal like this:
#item.QuoteItem.Sum(p => p.Subtotal)
I believe the reason I have this issue is that my Linq query above isn't retrieving the associated QuoteItems for each Quote.
To get a job and eager load all its quotes and their quoteitems, you write:
var job = db.Jobs
.Include(x => x.Quotes.Select(q => q.QuoteItems))
.Where(x => x.JobID == id)
.SingleOrDefault();
You might need SelectMany instead of Select if QuoteItems is a collection too.
Note to others; The strongly typed Include() method is an extension method so you need to include using System.Data.Entity; at the top of your file.
The method in the accepted answer doesn't work in .NET Core.
For anyone using .NET Core, while the magic string way does work, the cleaner way to do it would be ThenInclude:
var job = db.Jobs
.Where(x => x.JobID == id)
.Include(x => x.Quotes)
.ThenInclude(x => x.QuoteItems)
.SingleOrDefault();
Source: Work with data in ASP.NET Core Apps | Microsoft Learn
This will do the job (given that we are talking entity framework and you want to fetch child-entities):
var job = db.Jobs
.Include(x => x.Quotes) // include the "Job.Quotes" relation and data
.Include("Quotes.QuoteItems") // include the "Job.Quotes.QuoteItems" relation with data
.Where(x => x.JobID == id) // going on the original Job.JobID
.SingleOrDefault(); // fetches the first hit from db.
For more information about the Include statement have a look at this: https://learn.microsoft.com/en-us/dotnet/api/system.data.objects.objectquery-1.include
This answer has been getting upvotes throught the years, so I'd just like to clarify, try https://stackoverflow.com/a/24120209/691294 first. This answer is for those cases where all else fails and you have to resort to a black magic solution (i.e. using magic strings).
This did the trick for me as #flindeberg said here .
Just added checking if there are children in each parent item in the list
List<WCF.DAL.Company> companies = dbCtx.Companies.Where(x=>x.CompanyBranches.Count > 0)
.Include(c => c.CompanyBranches)
.Include("CompanyBranches.Address")
.ToList();
Related
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.
I've a structure based of list containing other list. I need to filter the list based on the value of a property based in the deepest part of the list.
Right now I'm doing this:
queryable = queryable
.Include(x => x.Carriers)
.ThenInclude(c => c.CarrierActions)
.ThenInclude(ca => ca.Action)
.ThenInclude(ac => ac.ActionFacts);
queryable = queryable
.Where(x => x.Carriers.Any(
carriers => carriers.CarrierActions.Any(
carrieractions =>
carrieractions.Action.ActionTypeId ==
ActionTypeEnum.DosemeterCalculateDeepDose)));
I join the needed tables, then I filter them based on the ActionTypeId based 3 levels below the top list.
First off all, is it possible to do this in 1 step ( include the filtering with the joins ), second of all, the second part is not working as my list gets empty, but I'm certain that actions with that type get values.
Using .NET Core 2.0.3 btw!
To answer your first part, you can do this
queryable = queryable
.Include(x => x.Carriers)
.ThenInclude(c => c.CarrierActions)
.ThenInclude(ca => ca.Action)
.ThenInclude(ac => ac.ActionFacts)
.Where(x => x.Carriers.Any(
carriers => carriers.CarrierActions.Any(
carrieractions =>
carrieractions.Action.ActionTypeId ==
ActionTypeEnum.DosemeterCalculateDeepDose)))
To your second part, it should be working, id check your data, as this is pretty straight forward
I have the following data model:
Agenda->AgendaSection->SectionItem
Starting with the Item, I need to fetch both the Section and Agenda.
I've tried the following (and other things):
IList<AgendaSectionItem> myTasks =
db.AgendaSectionItems.Where(i => i.AssigneeId == currentUser.UserId)
.Include(i => i.AgendaSection)
.Include(s => s.AgendaSection.Agenda)
.ToList();
However, the Agenda ends up being null.
Anyone know how to do this?
Thanks,
Philip
Try removing the first include statement. I have had issues in the past with multiple include calls for whatever reason. It should work with just the one call:
IList<AgendaSectionItem> myTasks =
db.AgendaSectionItems.Where(i => i.AssigneeId == currentUser.UserId)
.Include(s => s.AgendaSection.Agenda)
.ToList();
My models structure looks like this:
UserProgresses:dbset
LessonProgresses:List // The lesson progress a user has in one course
Lesson:Lesson // The general Lesson class.
Materials:List // A list of lesson materials
When I execute this query:
var progresses = context.UserProgresses
.Include(x => x.LessonProgresses.Select(y => y.Lesson.Materials))
.SingleOrDefault(x => x.Id == progressId);
This is the result I get after executing that query:
foreach (var lessonProgress in progress.LessonProgress)
{
lessonProgress.Lesson // Works
lessonProgress.Lesson.Materials // NULL
}
The interesting thing here is that when I insert the row below inside the loop and on the first line the Materials list gets populated.
context.Lessons.Include(x => x.Material)
.SingleOrDefault(x => x.Id == lesson.Lesson.Id);
I also checked the tables and the data is OK. I suspect that something is wrong with the Include statement.
Thanks.
Try to use a string to specify the relationships
var progresses = context.UserProgresses
.Include("LessonProgresses.Lesson.Materials")
.SingleOrDefault(x => x.Id == progressId);
MSDN documentation
Or try this
var progresses = context.UserProgresses
.Include(u => u.LessonProgress.Select(l => l.Lesson).Select(m => m.Materials))
.SingleOrDefault(x => x.Id == progressId);
So the problem was that the LessonProgress was untracked and was added way back in the callstack. The Lesson was set using:
lessonProgress.Lesson = context.Lessons.SingleOrDefault(x => x.Id == lessonId);
Without including Materials. After doing a Include there, everything was all good.
I have a table and one of the properties of the table is TotalDue.I wish to first order it by TotalDue and then select the "top" record which in this case would be the record with the highest value.
homeVM.LastSaleAmount = (from i in salesService.GetSalesOrderHeaders()
.OrderByDescending(a => a.TotalDue).First();
This is what I've tried so far but I think .First() needs a parameter and I think I need a select as well but not really sure.
You can try with Take method, is like top, but in Linq world.
homeVM.LastSaleAmount = salesService.GetSalesOrderHeaders().OrderByDescending(a => a.TotalDue).Take(1);
https://msdn.microsoft.com/en-us/library/vstudio/bb503062%28v=vs.100%29.aspx
You're mixing method syntax and query syntax, and your use of query syntax isn't necessary and making this harder. Just remove it:
homeVM.LastSaleAmount = salesService.GetSalesOrderHeaders()
.OrderByDescending(a => a.TotalDue)
.Select(a => a.TotalDue)
.First();
You are trying to put an entire entity into LastSaleAmount. use .Select(a => a.TotalDue) like:
homeVM.LastSaleAmount = salesService.GetSalesOrderHeaders()
.OrderByDescending(a => a.TotalDue).Select(a => a.TotalDue).First();