Althought documentation for the Session.Fetch method is very brief I got to understand it works for XPCollection only. Since we were advised by DevExpress to migrate our querying to use Linq to XPO with XPQuery I'm having a hard time figuring out how to do that.
The reason I need to do that is, of course, performance. I've got an aggergate root and I need to return data for a RESTful service which will be "denormalized". I really need something like nHibernate have:
C#session.Query<User>() .Fetch(e => e.Employer) .FetchMany(u => u.Orders) .ThenFetchMany(o => o.OrderItems
This way XPO woudln't emmit countless queries for each separate referenced property and could use a simple join to get all data in one round-trip.
(unless I'm mistaken I beleive referenced objects are lazily loaded, right?)
Here is what the context I'm trying to use it:
C#public class Root : XPObject
{
public Root(Session s) : base(s) { }
public string Name { get; set; }
public Child FirstChild { get; set; }
public Employer Employer { get; set; }
}
public class Child : XPObject
{
public Child(Session s) : base(s) { }
public string Name { get; set; }
}
public class Employer: XPObject
{
public Employer(Session s) : base(s) { }
public string Name { get; set; }
}
public class RootDto
{
public int rootId { get; set; }
public string rootName { get; set; }
public int firstChildId { get; set; }
public string firstChildName { get; set; }
public int employerId { get; set; }
public string employerName { get; set; }
}
public class RootsController : ApiController
{
public IEnumerable<RootDto> GetAllRoots()
{
var query = from r in new XPQuery<Root>(new Session())
orderby r.Employer.Name
select new RootDto
{
rootId = r.Oid,
rootName = r.Name,
employerId = r.Employer.Oid,
employerName = r.Employer.Name,
firstChildId = r.FirstChild.Oid,
firstChildName = r.FirstChild.Name,
};
return query;
}
}
I want XPO to issue a single SQL statement to the server, which it could do only if I could set prefetch to Employer and Child. Something like this:
C#public class RootsController : ApiController
{
public IEnumerable<RootDto> GetAllRoots()
{
var query = from r in new XPQuery<Root>(new Session()).Fetch("FirstChild", "Employer")
orderby r.Employer.Name
select new RootDto
{
rootId = r.Oid,
rootName = r.Name,
employerId = r.Employer.Oid,
employerName = r.Employer.Name,
firstChildId = r.FirstChild.Oid,
firstChildName = r.FirstChild.Name,
};
return query;
}
}
Or Fetch(c => new { c.FirstChild, c.Employer } if you like lambdas a lot…
Is there any way I could optmize this call without actually resorting to use SQL instead of XPO to retrive this data from the server? Am I wrong in assuming that XPO is lazy loading Employer and Child, which will require a round-trip to the server for each unloaded Child or Employer it finds when enumerating the results of this Web Api method?