NHibernate, get grandchildren collection using QueryOver w/ Future - c#

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

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");
}

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.

EF6 Condition based on sub child

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

How to efficiently select child objects through LINQ

In an effort to access child objects only through their aggregate roots, I am struggling to think of efficient ways to select the correct data. Could I rewrite the following to be more efficient/concise?
var jobReport = db.Jobs
.Where(j => j.JobReports.Any(jr => jr.ReportId == reportId))
.Select(j => j.JobReports.Single(jr => jr.ReportId == reportId))
.Single();
What you wrote would be equivalent to:
var jobReport = db.Jobs.SelectMany(j => j.JobReports)
.Single(jr => jr.ReportId == reportId);

LINQ to SQL querying across relationships

This is driving me mad. I thought it seemed simple enough but the below is returning a list of IEnumerable containing the entities I need, instead of just a list of entities:
db.tblPeople.Where(p => p.id == id).Select(s => s.tblCars.Select(z => z.tblCarType)).ToList();
My attempt is to retrieve a list of all carType entities associated with the personId.
I assume it's something to do with the last nested select?
Do like this because you are expecting multiple records to be returned:
var result = db.tblPeople
.Where(p => p.id == id)
.Select(s => s.tblCars
.SelectMany(z => z.tblCarType)).ToList();
Use SelectMany in order to flatten IEnumerable<IEnumerable<CarType>> into IEnumerable<CarType>.
var carTypes =
db.tblPeople
.Where(p => p.id == id)
.SelectMany(s =>
s.tblCars
.Select(z => z.tblCarType))
.ToList();
This translates from
var carTypes =
(from person in tblPeople
from car in person.tblCar
from carType in car.tblCarType
where person.id == id
select carType).ToList();
This is what you want/need:
db.tblPeople.Where(p => p.id == id).SelectMany(s => s.tblCars.Select(z => z.tblCarType)).ToList();

Categories