EF6 Condition based on sub child - c#

I have this C# code that works, but I'd like to be able to choose the Agency if a person is in it all in the query. Is there a way to do that all in the query?
var retVal = new List<Agency>();
var items=_db.Agencies
.Include(x => x.AgencyMembers.Select(y => y.Person))
.Where(w => w.NationId == User.NationId).ToList();
foreach (var agency in items)
{
if(agency.AgencyMembers.Any(c=>c.Person.Id==personId))
retVal.Add(agency);
}
return retVal;

You should be able to just add that predicate to your query.
return _db.Agencies
.Include(x => x.AgencyMembers.Select(y => y.Person))
.Where(w => w.NationId == User.NationId)
.Where(agency => agency.AgencyMembers.Any(c=>c.Person.Id==personId))
.ToList();
Depending what navigation properties you have, you may be able to simplify it by starting from the person.
return _db.People
.Single(p => p.Id == personId)
.Agencies
.Where(w => w.NationId == User.NationId)
.ToList();

You can try this:
var items=_db.Agencies
.Include(x => x.AgencyMembers.Select(y => y.Person))
.Where(agency=> agency.NationId == User.NationId && agency.AgencyMembers.Any(c=>c.Person.Id==personId))
.ToList();

Related

select parent and some childs with a filter by linq

I have three classes:
OrderSet - Order (1:n) and OrderDetail (1:n)
OrderSet and Order has each a property 'Status'.
I want a receive a construct with all OrderSet with Status='open' and all regarding Orders with Status='open'.
I tried this:
var orderSet = db.OrderSet
.Where(x => x.Status == 'Open')
.Where(x => x.Order.Any(y => y.Status == 'Open'))
.Include(x => x.Order.Select(q => q.OrderDetail))
But I got all Orders, also with Status 'Closed'.
What is my fault?
Thank you in advance.
If you want to ignore OrderSets which contain any Order that doesn't have an "Open" status, you may use:
var orderSets = db.OrderSet
.Where(os => os.Status == "Open" && os.Order.All(o => o.Status == "Open")
.Include(os => os.Order.Select(o => o.OrderDetail));
If you want to include those OrderSets but only ignore the child Orders that don't meet the said condition, there's probably no way to do that without modifying the collection of OrderSets returned by the query.
If that's what you want to do, one way to achieve that would be like this:
var orderSets = db.OrderSet
.Where(os => os.Status == "Open")
.Include(os => os.Order.Select(o => o.OrderDetail)).ToList();
foreach (var orderSet in orderSets)
{
orderSet.Order.RemoveAll(o => o.Status == "Open");
}

How to include two object inside the same select on Linq MVC5

I do have a complex query to select a full object called Performance
The Performance relationship with others objects is:
Performance has a list of Index
Index has a list of SubIndex
SubIndex has a list of Indicator
Indicator has a list of Item
Item relationship with Spot and Measurement:
Item has one Spot and one Measurement
The query below returns exactly what I want, but I would like to include the Spot and Measurement to the Item object.
return _context.Performance.Include(i => i.Indexes
.Select(s => s.SubIndexes
.Select(d => d.Indicators
.Select(t => t.Items))))
.SingleOrDefault(p => p.Id == id);
I have tried the query below and it is returning the Measurement object. How to include the Spot object?
return _context.Performance.Include(i => i.Indexes
.Select(s => s.SubIndexes
.Select(d => d.Indicators
.Select(t => t.Items.Select(tm => tm.Measurement)))))
.SingleOrDefault(p => p.Id == id);
You could add second Include too;
return _context.Performance.Include(i => i.Indexes
.Select(s => s.SubIndexes
.Select(d => d.Indicators
.Select(t => t.Items.Select(tm => tm.Measurement)))))
.Include(i => i.Indexes
.Select(s => s.SubIndexes
.Select(d => d.Indicators
.Select(t => t.Items.Select(tm => tm.Spot)))))
.SingleOrDefault(p => p.Id == id);

Using Include() with anonymous types in Entity Framework

I am trying to eager load some properties using Include method as following:
var dbData = dbContext.Locators.Include(x => x.PhysicalObjects.Select(p => p.Parent)).Include(x => x.PhysicalObjects.Select(p =>p.Type.AllowedSubTypes))
.Where(x => x.id==1)).Select(x => new
{
newContainer = x.PhysicalObjects.Where(p => p.Id== newContainerId).FirstOrDefault(),
phyiscalObject = x.PhysicalObjects.Where(p => p.Id == id).FirstOrDefault()
}).FirstOrDefault();
But it returns Parent and Type properties as null(I checked database they are not null).
So how can I eager load those properties?
P.S
I am using Entity Framework V6.1.3
Depending on DevilSuichiro's comment above the query will be like this:
var dbData = dbContext.Locators.Include(x => x.PhysicalObjects.Select(p => p.Parent)).Include(x => x.PhysicalObjects.Select(p =>p.Type.AllowedSubTypes))
.Where(x => x.Id==1)).Take(2).ToList().Select(x => new
{
newContainer = x.PhysicalObjects.Where(p => p.Id== newContainerId).FirstOrDefault(),
phyiscalObject = x.PhysicalObjects.Where(p => p.Id == id).FirstOrDefault()
}).FirstOrDefault();
It worked for me, but I will still be waiting for better answer if any.

The Include path expression must refer to a navigation property defined on the type.

My linq query
model.Questions = db.Questions
.Where (x => x.CategoriesID == categoryId)
.Include (qc => qc.QuestionCounters.Where(x => x.MemberID == User.Identity.GetUserId()))
.Include (qf => qf.QuestionFavorites.Where(x => x.MemberId == User.Identity.GetUserId()))
.Include (qt => qt.QuestionTags)
.ToList();
produces the 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.'
Any ideas why is this happening?
As some people commented, you cannot use Where method in Include.
Disclaimer: I'm the owner of the project Entity Framework Plus
EF+ Query IncludeFilter feature allow filtering related entities.
model.Questions = db.Questions
.Where (x => x.CategoriesID == categoryId)
.IncludeFiler (qc => qc.QuestionCounters.Where(x => x.MemberID == User.Identity.GetUserId()))
.IncludeFiler (qf => qf.QuestionFavorites.Where(x => x.MemberId == User.Identity.GetUserId()))
.IncludeFiler (qt => qt.QuestionTags)
.ToList();
Wiki: EF+ Query IncludeFilter
Solution #2
Another technique is by using projection (which is what my library do under the hood)
bd.Questions
.Select(q = new {
Question = q,
QuestionCounters = q.QuestionCounters.Where(x => x.MemberID == memberId),
QuestionFavorites = q.QuestionFavorites.Where(x => x.MemberId == memberId),
QuestionTags = q.QuestionTags
})
.ToList()
.Select(x => x.Question)
.ToList();
Ok. Ended up with
IQueryable<HomeViewModel> test = db.Questions
.Where(x => x.CategoriesID == categoryId)
.Select(q => q.ToHomeViewModel(User.Identity.GetUserId()));
and
public static HomeViewModel ToHomeViewModel(this Question q, string memberId)
{
return new HomeViewModel()
{
QuestionCounters = q.QuestionCounters.Where(x => x.MemberID == memberId),
QuestionFavorites = q.QuestionFavorites.Where(x => x.MemberId == memberId),
QuestionTags = q.QuestionTags
};
}
How needs include after all? ;)
Thanks for commenting #jle

NHibernate, get grandchildren collection using QueryOver w/ Future

I'm trying to retrieve all collections (non-cartesian product) of a parent entity, but can't figure out how to get the grandchildren. Table structure looks like:
The following code gets my parent and its Child1 and Child2 collections, as well as its ParentChild3 collection, but I do not know how to structure the query to get the Child3 grandchildren (and defer them to Future()).
var parent = _session
.QueryOver<Parent>()
.Where(x => x.Id == id)
.Future<User>();
var children1 =_session
.QueryOver<Parent>()
.Where(x => x.Id == id)
.Fetch(x => x.Children1).Eager
.Future<Parent>();
var children2 =_session
.QueryOver<Parent>()
.Where(x => x.Id == id)
.Fetch(x => x.Children2).Eager
.Future<Parent>();
var parentChildren3 =_session
.QueryOver<Parent>()
.Where(x => x.Id == id)
.Fetch(x => x.ParentChildren3).Eager
.Future<Parent>();
// how to get children3, now?
return parent.SingleOrDefault();
Semi-related: is this the best way to get all collections? Is it better (and possible) to use a query that obtains the result with joins instead?
how to get Children3:
ParentChildren alias = null;
var parentChildren3 =_session
.QueryOver<Parent>()
.Where(x => x.Id == id)
.JoinAlias(x => x.ParentChildren3, () => alias)
.Fetch(() => alias.Children3).Eager
.Future<Parent>();
Semi-related: It is the best way i know of.
If the ParentChild table does not have additional columns then you could map it as standard manytomany. NHibernate won't need entities for the link table then and the eager fetching will be easier.
Try this:
var parentChildren3 =
_session
.QueryOver<Parent>()
.Fetch(x => x.ParentChildren3).Eager
.Fetch(x => x.ParentChildren3.First().Child3).Eager
.Where(x => x.Id == id)
.Future<Parent>();
As explained on this forum thread: https://groups.google.com/forum/?fromgroups=#!topic/nhusers/ER5BvVnCT5Q

Categories