Fluent Api Include Where Clause [duplicate] - c#

This question already has answers here:
EF: Include with where clause [duplicate]
(5 answers)
Closed 6 years ago.
I need to get products with cover picture. But when i add pic => pic.IsCover it's throw exception.Otherwise there is no problem. How can i fixed it?
Error:
The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.
Parametre adı: path
Thanks to all
_db.ProdSmartSorts
.Where(x => catIds.Contains((int)x.Product.CategoryId))
.OrderBy(x => x.ProdSmartId)
.Select(x => x.Product)
.Include(p => p.Pictures.Where(pic => pic.IsCover))
.Skip(prodCount * (pageNumber - 1))
.Take(prodCount)
.ToList();

Entity Framework does not support filtering with the Include method. You can vote for it here, though: https://entityframework.codeplex.com/workitem/47

Does placing the .Include() method call directly after the DbSet work? i.e.
_db.ProdSmartSorts
.Include(p => p.Pictures)
.Where(x => catIds.Contains((int)x.Product.CategoryId))
.OrderBy(x => x.ProdSmartId)
.Select(x => x.Product)
.Skip(prodCount * (pageNumber - 1))
.Take(prodCount)
.ToList();
I think the Include method is only available on the DbSet objects within the dbContext. If you try and put it further down the chain you only have methods that are available to IQueryable or IEnumerable objects dependant on the circumstances.
Also, to my knowledge you can't use the Include function to filter, as you attempted. So you will have to load all images related Picture entities.
EDIT: Sorry - just realised that this question is specifically asking for filtering on the Include() method. Please disregard.

Related

EF include with where clause db first [duplicate]

This question already has answers here:
Entity Framework Include with condition
(4 answers)
Closed 5 years ago.
I am aware of the other similar question at the link below, but those answers do not work as I am db first and the entity framework plus solution is very slow and appears to just get every record and filter it out afterwards.
EF: Include with where clause
drivers and passengers are navigational properties on busses. preferredBrands is a List<String>. So basically what I want is all busses where typeid = 2, all drivers where their preferredbrand is listed in the preferredbrand list, and all passengers. The query below throws exception:
The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.
Parameter name: path
Query:
var result = db.busses.Where(h => h.bussesTypeId.Equals(2))
.Include(h => h.drivers.Where(p => preferredBrands.Contains(p.PreferredBrand)))
.Include(h => h.passengers).ToList();
'Include' only accepts string parameter and not delegate. You have to place the Relational property in quote (string). Do this instead
var result = db.busses
.Include("drivers.preferredBrands")
.Include("passengers")
.Where(h => h.bussesTypeId.Equals(2));
To access drivers, use
result.drivers.where(p => preferredBrands.Contains(p.PrefferedBrand));
However, if you must use delegate in your include, then
1. Reference Z.EntityFramework from Nuget
2. Then you can use 'IncludeFilter' instead as follows;
using Z.EntityFramework.Plus;
var result = db.busses
.IncludeFilter(h => h.drivers.Where(p => preferredBrands.Contains(p.PrefferedBrand)))
.IncludeFilter(h => h.passengers)
.Where(h => h.bussesTypeId.Equals(2)).ToList();
Note: You must use the Include or IncludeFilter before the where clause. It must be used directly on the EF Entity and not just on any IEnumerable

Entity Framework Core SelectMany then Include

I cant seem to figure out how to get EF Core to include / load related objects when using SelectMany.
context.MyObject
.Where(w => w.Id == Id)
.SelectMany(m => m.SubObject)
.Include(i => i.AnotherType)
Would have thought something like the above would work, however the collapsed SubObject collection has the AnotherObject being null and not included.
Been searching for hours.
Any help would be appreciated.
Thanks
Would have thought something like the above would work
It used to work in EF6, but currently is not supported by EF Core - it allows you to use eager load only the entity which the query starts with, as mentioned in the Loading Related Data - Ignored Includes section of the documentation:
If you change the query so that it no longer returns instances of the entity type that the query began with, then the include operators are ignored.
So to get the eager loading work in your scenario, the query should be like this (assuming you have inverse navigation or FK property in SubObject):
context.SubObject
.Where(so => so.Object.Id == Id) // or so.ObjectId == Id
.Include(i => i.AnotherType)

Linq querying my include-statement [duplicate]

This question already has answers here:
EF: Include with where clause [duplicate]
(5 answers)
Closed 5 years ago.
Here is my expression:
Course course = db.Courses
.Include(
i => i.Modules.Where(m => m.IsDeleted == false)
.Select(s => s.Chapters.Where(c => c.IsDeleted == false))
).Include(i => i.Lab).Single(x => x.Id == id);
I know the cause is Where(m => m.IsDeleted == false) in the Modules portion, but why does it cause the error? More importantly, how do I fix it?
If I remove the where clause it works fine but I want to filter out deleted modules.
.Include is used to eagerly load related entities from the db. I.e. in your case make sure the data for modules and labs is loaded with the course.
The lamba expression inside the .Include should be telling Entity Framework which related table to include.
In your case you are also trying to perform a condition inside of the include, which is why you are receiving an error.
It looks like your query is this:
Find the course matching a given id, with the related module and lab. As long as the matching module and chapter are not deleted.
If that is right, then this should work:
Course course = db.Courses.Include(c => c.Modules)
.Include(c => c.Lab)
.Single(c => c.Id == id &&
!c.Module.IsDeleted &&
!c.Chapter.IsDeleted);
but why does it cause the error?
I can imagine that sometimes the EF team regrets the day they introduces this Include syntax. The lambda expressions suggest that any valid linq expression can be used to subtly manipulate the eager loading. But too bad, not so. As I explained here the lambdas only serve as a disguised string argument to the underlying "real" Include method.
how do I fix it?
Best would be to project to another class (say, a DTO)
db.Courses.Select(x => new CourseDto {
Id = x.Id,
Lab = x.Lab,
Modules = x.Modules.Where(m => !m.IsDeleted).Select( m => new ModuleDto {
Moudle = m,
Chapters = x.Chapters.Where(c => c.IsDeleted)
}
}).Single(x => x.Id == id);
but that may be a major modification for you.
Another option is to disable lazy loading and pre-load the non-deleted Modules and Chapters of the course in the context by the Load command. Relationship fixup will fill the right navigation properties. The Include for Lab will work normally.
By the way, there is a change request for this feature.

EF Lambda: The Include path expression must refer to a navigation property [duplicate]

This question already has answers here:
EF: Include with where clause [duplicate]
(5 answers)
Closed 5 years ago.
Here is my expression:
Course course = db.Courses
.Include(
i => i.Modules.Where(m => m.IsDeleted == false)
.Select(s => s.Chapters.Where(c => c.IsDeleted == false))
).Include(i => i.Lab).Single(x => x.Id == id);
I know the cause is Where(m => m.IsDeleted == false) in the Modules portion, but why does it cause the error? More importantly, how do I fix it?
If I remove the where clause it works fine but I want to filter out deleted modules.
.Include is used to eagerly load related entities from the db. I.e. in your case make sure the data for modules and labs is loaded with the course.
The lamba expression inside the .Include should be telling Entity Framework which related table to include.
In your case you are also trying to perform a condition inside of the include, which is why you are receiving an error.
It looks like your query is this:
Find the course matching a given id, with the related module and lab. As long as the matching module and chapter are not deleted.
If that is right, then this should work:
Course course = db.Courses.Include(c => c.Modules)
.Include(c => c.Lab)
.Single(c => c.Id == id &&
!c.Module.IsDeleted &&
!c.Chapter.IsDeleted);
but why does it cause the error?
I can imagine that sometimes the EF team regrets the day they introduces this Include syntax. The lambda expressions suggest that any valid linq expression can be used to subtly manipulate the eager loading. But too bad, not so. As I explained here the lambdas only serve as a disguised string argument to the underlying "real" Include method.
how do I fix it?
Best would be to project to another class (say, a DTO)
db.Courses.Select(x => new CourseDto {
Id = x.Id,
Lab = x.Lab,
Modules = x.Modules.Where(m => !m.IsDeleted).Select( m => new ModuleDto {
Moudle = m,
Chapters = x.Chapters.Where(c => c.IsDeleted)
}
}).Single(x => x.Id == id);
but that may be a major modification for you.
Another option is to disable lazy loading and pre-load the non-deleted Modules and Chapters of the course in the context by the Load command. Relationship fixup will fill the right navigation properties. The Include for Lab will work normally.
By the way, there is a change request for this feature.

EntityFramework 5 filter an included navigation property

I would like to find a way using Linq to filter a navigation property to a subset of related entities. I know all answers around this subject suggest doing an anonymous selector such as:
query.Where(x => x.Users.Any(y => y.ID == actingUser.ID))
.Select(x => new
{
Event = x,
Discussions = x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())
})
.OrderBy(x => x.Discussions.Count())
.ThenBy(x => x.Event.Name);
However, this is significantly less than ideal due to the general nature of our query generation and also yields significantly horrific sql queries if you throw up profiler.
I would like to be able to accomplish something like:
query.Include(x => x.Discussions.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>()))
.OrderBy(x => x.Discussions.Count())
.ThenBy(x => x.Name);
I realize that this is not supported in EF5 (or any version for that matter) but there has to be a way to accomplish constraining the result set through Linq without delving into anonymous type select statements.
I have attempted doing something to the tune of:
query.GroupJoin(discquqery,
x => x.ID,
x => x.Event.ID,
(evt, disc) => evt.Discussions = disc.Where(actingUser.GenerateSecurityFilterFor<Domain.Discussion>())).ToList();
However you cannot have assignment inside a lambda expression and selecting an anonymous type here causes the same dilemma that it does using the select.
I guess I cannot comprehend why EF does not provide a way (that I can find) to generate:
SELECT
--Properties
FROM Event e
LEFT OUTER JOIN Discussions d
ON e.ID = d.EventID AND --Additional constraints
WHERE
--Where conditions
ORDER BY
--Order Conditions
It is so simple to constrain the join in SQL there HAS to be a way to do it through Linq as well.
PS: I have searched stack, MSDN, experts-exchange, etc. Please realize this is not a duplicate. Anything even touching on this subject either has a cop-out "It can't be done" answer or no answer at all. Nothing is impossible... including this.
Anything even touching on this subject either has a cop-out "It can't
be done" answer or no answer at all. Nothing is impossible...
including this.
Sure. It is possible. You can download EF source code and add this feature yourselves. It will be great contribution to open source project and the community. I believe EF team will gladly help you with your effort.
With the current version "it can't be done" is the answer. You can either use projection to anonymous or special unmapped type as you have described in the beginning of your question. Other options are separate explicit query to load related entities for single parent or separate query to load related entities for all parents.
Load relations for single parent:
context.Entry(event)
.Collection(e => e.Discussions)
.Query()
.Where(d => ...)
.Load();
Load relations for all parents (requires lazy loading to be turned off):
// load all parents
var events = query.Where(e => ...).ToList();
// load child filtered by same condition for parents and new condition for children
childQuery.Where(d => e.Event ... && d.Something ...).Load();
The second solution requires child to have navigation property back to parent (for constructing same query condition used initially to loads parent). If you have everything correctly configured and entities are attached EF should automatically fix your relations (collections) in parent entities (but it will not mark collection in dynamic proxy as loaded so that is the reason why you cannot use this together with lazy loading).

Categories

Resources