Lambda Expression to filter Included Entities - c#

I have this query,
var productCategories = _dbContext
.Set<ProductCategory>()
.Include(x => x.ProductInCategories)
.ThenInclude(x => x.Product)
.ThenInclude(x => x.ProductMetadatas)
.Where(x => x.Active)
.ToList();
But, I can't filter products in this query. I just want to have the Active Products. Any Help will be appreciated.

Related

EF Core Linq query containing Any cannot be translated [duplicate]

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();

Multiple levels with theninclude not returning all rows unless I query the detail

I'm using .net core 2.0 (I know) and I've got nested data I'm pulling from sql.
The weird thing is that some of the data isn't showing up unless I explicitly search for it.
var record = db.Records
.Include(x => x.ParentLabels)
.Include(x => x.TopChildren)
.ThenInclude(x => x.LevelTwoChildren)
.ThenInclude(x => x.LevelThreeChildren)
.ThenInclude(x => x.LevelTwoChildren.LevelTwoLabels)
.FirstOrDefault(x => x.Id.Equals(id));
The weird thing is that some of the LevelTwoChildren.Labels data does not show up, UNLESS I add the following:
var t = record.TopChildren.FirstOrDefault();
var tt = t.LevelTwoChildren.FirstOrDefault(x => x.Id.Equals(id2));
I've tried doing a foreach through all the record levels but that doesn't help.
Any ideas?
I guess it is happening because of .ThenInclude(x => x.LevelTwoChildren.LevelTwoLabels). Include statements should include one property at a time. What you should do is:
var record = db.Records
.Include(x => x.ParentLabels)
.Include(x => x.TopChildren)
.ThenInclude(x => x.LevelTwoChildren)
.ThenInclude(x => x.LevelThreeChildren)
.Include(x => x.TopChildren)
.ThenInclude(x => x.LevelTwoChildren)
.ThenInclude(x => x.LevelTwoLabels)
.FirstOrDefault(x => x.Id.Equals(id));

LINQ expression to filter

I have the following LINQ expression where I am fetching Courses, Students that belong to that Course, then the School's where the Student's goes to. The following LINQ expression works fine.
However, I need to further, filter it where I need to get Students with the City == 'Colarado'. How can I alter the following LINQ to my use case.
_dbContext.Courses
.Where(c => c.Id == Id)
.Include(c => c.Students)
.ThenInclude(c => c.Schools)
.OrderByDescending(c => c.Id)
.ToListAsync();
If you need all courses and only filter students - since EF Core 5.0 you can use filtered include:
_dbContext.Courses
.Where(c => c.Id == Id)
.Include(c => c.Students.Where(s => s.City == "Colarado"))
.ThenInclude(c => c.Schools)
.OrderByDescending(c => c.Id)
.ToListAsync();
You can do the filter in the Where method.
_dbContext.Courses
.Where(c => c.Id == Id && c.Students.All(s => s.City == "Colarado"))
.Include(c => c.Students)
.ThenInclude(c => c.Schools)
.OrderByDescending(c => c.Id)
.ToListAsync();

EF Core 3.0 .Include() chain taking ~5-10x longer than 2.2

I'm having trouble with a large EF Core query that has a lot of chained .Include().
I have a linq query that looks like this:
_context.Equipment.Include(x => x.Group)
.Include(x => x.Status)
.Include(x => x.Area)
.Include(x => x.EquipmentType)
.Include(x => x.Parts).ThenInclude(x => x.ChildrenParts)
.Include(x => x.Parts).ThenInclude(x => x.ParentParts)
.Include(x => x.Parts).ThenInclude(x => x.Vendor)
.Include(x => x.Notes)
.Include(x => x.Department)
.Include(x => x.PMaintenance)
.Include(x => x.SystemInfo).ThenInclude(x => x.SystemUsers)
.Include(x => x.SystemInfo).ThenInclude(x => x.Frameworks)
.Include(x => x.SystemInfo).ThenInclude(x => x.VideoCards)
.Include(x => x.SystemInfo).ThenInclude(x => x.StorageDrives)
.Include(x => x.SystemInfo).ThenInclude(x => x.Software)
.Include(x => x.SystemInfo).ThenInclude(x => x.NetworkAdapters)
.Include(x => x.SystemInfo).ThenInclude(x => x.Printers)
.Include(x => x.MaintenanceHours)
.Include(x => x.Attachments)
.Include(x => x.Request)
.FirstOrDefault(x => x.EquipmentId == id);
In EF Core 2.2, this took less than a few seconds to evaluate. Now on EF Core 3.0, it takes about 15 seconds to complete. What about EF Core 3 made this so slow? I read here that ef now creates one sql statement per linq query, but I don't see how the statement would have changed in this instance. Can I do something to this query that would decrease the execution time?
EDIT: This is on SQL Server v11.0.3
Try it like this. You might need to change some of the "Select" and "SelectMany" options and the Id field names as you did not post the context.`
var query = _context.Equipment.Include(x => x.Group)
.Include(x => x.Status)
.Include(x => x.Area)
.Include(x => x.EquipmentType)
.Include(x => x.Notes)
.Include(x => x.Department)
.Include(x => x.PMaintenance)
.Include(x => x.MaintenanceHours)
.Include(x => x.Attachments)
.Include(x => x.Request).FirstOrDefault(x => x.EquipmentId == id);
query.Include(x => x.Parts).ThenInclude(x => x.ChildrenParts).SelectMany(x => x.Parts).Where(a => query.Select(q => q.PartsId).Contains(a.Id)).Load();
query.SelectMany(x => x.Parts).SelectMany(x => x.ChildrenParts).Load();
query.SelectMany(x => x.Parts).SelectMany(x => x.ParentParts).Load();
query.SelectMany(x => x.Parts).Select(x => x.Vendor).Load();
query.Include(x => x.SystemInfo).ThenInclude(x => x.SystemUsers).SelectMany(x => x.SystemInfo).Where(a => query.Select(q => q.SystemInfoId).Contains(a.Id)).Load();
query.SelectMany(x => x.SystemInfo).SelectMany(x => x.Frameworks).Load();
query.SelectMany(x => x.SystemInfo).SelectMany(x => x.VideoCards).Load();
query.SelectMany(x => x.SystemInfo).SelectMany(x => x.StorageDrives).Load();
query.SelectMany(x => x.SystemInfo).SelectMany(x => x.Software).Load();
query.SelectMany(x => x.SystemInfo).SelectMany(x => x.NetworkAdapters).Load();
query.SelectMany(x => x.SystemInfo).SelectMany(x => x.Printers).Load();
query.ToList();
Hope this helps.

EF serializes entity to json with included related entities creates a loop

I am using EF in my WebApi project. I have a database including many tables which are related to each other. When I serialize objects coming from tables, it creates a weird json.
My EF query is like below.
db.Products.Include(x => x.ProductCategoryRelations)
.Include(x => x.ProductCategoryRelations.Select(c => c.Category))
.Include(x => x.ProductFileRelations)
.Include(x => x.ProductFileRelations.Select(c => c.File))
.Include(x => x.ProductPropertyRelations)
.Include(x => x.ProductPropertyRelations.Select(c => c.Property))
.Include(x => x.ProductColorRelations)
.Include(x => x.ProductColorRelations.Select(c => c.Color))
.Include(x => x.Brand)
.Where(predicate)
.ToListAsync();
Because of this EF query. It creates a json like below, which is not acceptable...
1.Product
2.Brand
3.Product
4.ProductCategoryRelations
5.Product
.....
.....
.....
.....
How can I fix this? I would like to have array of products but I am not what I need to change to get such a result. Any help would be appreciated.
Thanks in advance
Try this method:
db.Products
.Where(predicate)
.Select(p=> new { p.Brand, p.ProductColor.Color_Name, p.ProductCategory.Category_Name })
.ToListAsync();

Categories

Resources