New Posts New Posts RSS Feed: IEnumerable named query with includes not working
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

IEnumerable named query with includes not working

 Post Reply Post Reply
Author
AuerRo View Drop Down
Newbie
Newbie
Avatar

Joined: 14-Mar-2011
Location: Tyrol, Austria
Posts: 21
Post Options Post Options   Quote AuerRo Quote  Post ReplyReply Direct Link To This Post Topic: IEnumerable named query with includes not working
    Posted: 11-Apr-2012 at 7:55am
Hi,
I have a named query returning IEnumerable<T> like this:


public IEnumerable<Customer> GetCustomerWithCalculations()
{
    var entities = new EntityQuery<Customer>()
        .Include(Customer.PathFor(x => x.City.Region.Nation.Continent))
        .Where(x => x.Name.StartsWith("A"))
        .Execute();

    entities.ForEach(x =>
                         {
                             x.CalculateRevenue();
                             x.CalculateOpenAmount();
                         });

    return entities;
}



Everything except the include works as expected. If I change the named query to return IQueryable<T>, the include works as expected, but of course the ForEach has no effect. The calculations have to be on the server side, so in the end IQueryable<T> is no option.

I did not find anything like this mentioned in the docs, so I assume this is an error on my side. But I have no idea what to change that the include takes affect!

Thanks for any hint to solve this in advance!

Best regards, Roland
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 715
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 12-Apr-2012 at 3:51pm
Hi Roland,

I'm able to see the issue here. I'm going to check with a senior engineer to find out whether this is a bug or just a known limitation when returning an IEnumerable. 

FYI, the Include works on the server, i.e. inside the named query, you can actually see that the included entities are being returned from the db to the server. They're just not being returned/serialized from the server to the client as well.

Since you must execute the calculations on the server, one suggestion is to return IQueryable, intercept the query results on the server and execute the calculations. This way you can keep the client side query call the same and not have to change anything there.

public class MyQueryInterceptor : EntityServerQueryInterceptor {
  protected override bool ExecuteQuery() {

      //calls base.ExecuteQuery to execute and returns results
      base.ExecuteQuery();

      //Do special calculations for your particular named query here
      PerformAdditionalCalculationsToCustomerResults();
  }
  
  private void PerformAdditionalCalculationsToCustomerResults() {
      var entityQuery = this.Query as EntityQuery;

      if (entityQuery != null && 
          entityQuery.IsNamedQuery && 
          entityQuery.NamedQueryMethod.Name.Contains("CustomerWithCalculations")) {
        
          if (this.QueriedEntities.Any()) {
            this.QueriedEntities.OfType<Customer>().ForEach(c => {
                                                 c.CalculateRevenue();
                                                 c.CalculateOpenAmount();
                                              });
          }
      }
   }
}

Another suggestion that does require you to change client side code is to use Remote Server Method. See http://drc.ideablade.com/xwiki/bin/view/Documentation/rsmc-query. This is just another option.

I'll keep you updated as to whether this is a bug or not.


Edited by DenisK - 12-Apr-2012 at 4:09pm
Back to Top
AuerRo View Drop Down
Newbie
Newbie
Avatar

Joined: 14-Mar-2011
Location: Tyrol, Austria
Posts: 21
Post Options Post Options   Quote AuerRo Quote  Post ReplyReply Direct Link To This Post Posted: 13-Apr-2012 at 1:05am
Hi Denis!

Thanks for your help!

I implemented the solution "Named queryable and using the EntityServerQueryInterceptor" and it works. I assume that your ExecuteQuery-mehtod should rather look like this:
 
protected override bool ExecuteQuery() {

      //calls base.ExecuteQuery to execute and returns results
      var baseQueryResult = base.ExecuteQuery();

      //Do special calculations for your particular named query here
if(baseQueryResult)
      PerformAdditionalCalculationsToCustomerResults();

return baseQueryResult;
  }
Anyway, I'm not fully satisfied with this solution, as I'm force to tear one query into two parts. As the pattern of these queries is always the same (defaultquery + includes + where-constraint + entity-calculations) I was wondering, if I need the named query at all.

There is a Tag-property in every EntityQuery. Can I add a custom string value (eg: "ApplyCustomerCalculations") on the client as EntityQuery.Tag, check this Tag value on the server in the EntityServerQueryInterceptor.ExecuteQuery and start the same calculations? So I wouldn't need the named query, and everything stays in two places, not in three (means Client-Repository - ESQInterceptor and not Client-Repository - NamedQuery - ESQInterceptor).

Of course, overall, I'd prefer to be able to solve this in a named query only, so I'd rather hope this is a bug than a feature. ;)

Have a nice weekend
Roland


Edited by AuerRo - 13-Apr-2012 at 1:06am
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 715
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 13-Apr-2012 at 11:36am
Yes, you're correct. Of course we want to check if base.ExecuteQuery succeeds or not. 

Your suggestion of using EntityQuery.Tag is certainly another option. And yes, you can assign it a custom string and check the value on the server. I didn't suggest it since I was thinking you want to keep the named query call structure the same so you can easily remove the interceptor part if it turns out to be a bug and it's fixed.


Edited by DenisK - 13-Apr-2012 at 11:37am
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 715
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 16-Apr-2012 at 5:21pm
Hi Roland,

It turns out that this is not a bug. This is something that we just don't support. An Include can only work with an EntityQuery. We can, however, add this as a feature if we have more requests for this type of scenario in the future.


Edited by DenisK - 16-Apr-2012 at 5:46pm
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down