Hierarchical sets -> when are the IQueryables executed?

Posts   
 
    
Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 02-Mar-2010 23:53:43   

Using the sample query in the documentation under the title "Hierarchical sets", I constructed the following query...



var result = from wo in metaData.WorkOrder
             join proj1 in metaData.Project on wo.ProjectId equals proj1.ProjectId
             where wo.WorkOrderId == workOrderId
             select new
             {
                 WorkOrderId = wo.WorkOrderId,
                 LoanNumber = wo.LoanNumber,
                 BorrowerName = wo.BorrowerName,
                 ClientReferenceNumber = wo.ClientReference,
                 DueDate = wo.DueDate,
                 EnteredDate = wo.EnteredDate,
                 StatusLastUpdated = wo.StatusLastUpdated,
                 StatusId = wo.StatusId,

                 Project = from proj in metaData.Project
                           where proj.ProjectId == wo.ProjectId
                           select new
                           {
                               ProjectId = proj.ProjectId,
                               ConfirmationNumber = proj.ConfirmationNbr,
                               ReceivedDate = proj.ReceivedDate,
                               ProjectName = proj.ProjectName
                           },
                 Product = from negProd in metaData.NegotiatedProduct
                           where negProd.NpId == proj1.NpId
                           select new
                           {
                               DisplayText = negProd.DisplayText,
                               ProductName = negProd.NpName
                           }
             };

In the anonymous type that is being built in the code sample above, the members "Project" and "Product" are of type IQueryable.

Question1: When are these queries executed? I am guessing they dont execute until I call First(), FirstOrDefault() etc.

Question 2: In order to access the values / entities associated with these members do I need to write the code below, or is there another way, aside from "prefetches"?



foreach (var item in result)
{
    var project = item.Project.FirstOrDefault();
    var product = item.Product.FirstOrDefault();

    return new WorkOrderHeader
    {
        ProjectId = project.ProjectId,
        ConfirmationNumber = project.ConfirmationNumber,
        WorkOrderId = item.WorkOrderId,
        ProductName = product.ProductName
    };
}

Question 3: If I want to project into an object using the "Hierarchial Sets" method that we are talking about here, am I required to project into an "Anonymous Type" or can I project into a known type? i.e. can I project directly into WorkOrderHeader?

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 03-Mar-2010 10:38:21   

Question1: When are these queries executed? I am guessing they dont execute until I call First(), FirstOrDefault() etc.

Once you iterate the parent queryable item ("result" in this case), the queries are executed.

Question 2: In order to access the values / entities associated with these members do I need to write the code below, or is there another way, aside from "prefetches"?

foreach (var item in result) { var project = item.Project.FirstOrDefault(); var product = item.Product.FirstOrDefault();

return new WorkOrderHeader
{
    ProjectId = project.ProjectId,
    ConfirmationNumber = project.ConfirmationNumber,
    WorkOrderId = item.WorkOrderId,
    ProductName = product.ProductName
};

}

Where are the prefetches?

Question 3: If I want to project into an object using the "Hierarchial Sets" method that we are talking about here, am I required to project into an "Anonymous Type" or can I project into a known type? i.e. can I project directly into WorkOrderHeader?

Why using the "Hierarchical Sets" over PrefetchPaths? It seems to me your case is a typical PrefetchPath scenario, as you want to fetch a graph of entities. (WorkOrder and its related Project and Product entities).

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 06-Mar-2010 01:23:09   

Hello, thanks for the reply.

Regarding Q2 -> there are no prefetches in the code sample shown. I know that I could use prefetches to do what I want, but I dont want to. that is why I asked the question. is there another way without using the prefetch approach.

Regarding Q3 -> Long story short, I am comfortable with linq and I prefer using projections vs. cluttering my code with prefetches.

I prefer to get only the data that I need. I find the prefetch syntax combined with linq is not very intuitive. When I do a projection, only the fields that I choose are in the result set and the select list. Some of our entities in the DB have blob's associated with them, so I dont want to get that stuff right now. Plus linq + prefetch + include / exclude fields gets ugly real quick. if I were going to do that I may as well use the Classic Adapter Approach. One of the goals of linq IMO is to simplify the code, make things more declarative / functional, etc.

So Question 3 is still outstanding. Must I use anonymous types or can I use concrete types with projections?

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 07-Mar-2010 23:11:17   

You have to user anonymous types, or in the last projection in the "new" keyboard you can create an instance of your own custom classes or even instantiate LLBLGen entities. But anonymous types is the natural way to go. If you have blob fields etc, you can use IncludeExludeFields classes to avoid fetch some fields if you want (more info).

David Elizondo | LLBLGen Support Team