Array of Type as Expression parameter

6 posts, 0 answers
  1. Sverre
    Sverre avatar
    19 posts
    Member since:
    Sep 2008

    Posted 19 Nov 2012 Link to this post

    Hi!

    I have an abstract base-class: MyBaseClass, with subclasses MySubClass1MySubClass2MySubClass3MySubClass4 and so on...

    I am trying to construct a Linq query that will return objects of a specified number of subclasses. Some times I may want it to return MySubClass1-objects and MySubClass3-objects, and at another time it may be required to return MySubClass1, -2 and -4 objects. The combination is determined at run-time.

    As far as I can understand, I need to query the MyBaseClassExtent(), and somehow filter on types in the Where-part of the expression.

    I've been trying "forever" to come up with a way to do this, but most of my attempts end up with an error message stating that "Execution of 'blah blah' on the database server side currently not implemented"

    How can i build a dynamic Expression tree that includes filtering for a varying number of class-types? Is it possible at all?

    BTW: It is not a viable option to fetch all objects, and then filter on the client-side. The database is too big...

    Regards
    Sverre H.
  2. Viktor Zhivkov
    Admin
    Viktor Zhivkov avatar
    291 posts

    Posted 22 Nov 2012 Link to this post

    Hello Sverre,

    I guess you are using Horizontal Inheritance strategy for these queries. If it is the case it is impossible to do a LINQ query that you would like to have.
    Can you switch to different inheritance strategy?
    Can you live with non-abstract base class?

    If you can accept these changes we should be able to try to find a solution to implement properly your scenario.

    Greetings,
    Viktor Zhivkov
    the Telerik team
    Telerik OpenAccess ORM Meets ASP.NET Web API. Read more.
  3. DevCraft banner
  4. Sverre
    Sverre avatar
    19 posts
    Member since:
    Sep 2008

    Posted 22 Nov 2012 Link to this post

    Hi Viktor!

    Thank You for your reply! 

    I am actually using a Flat inheritance strategy or Flat Mapping as it is called in the ORM Classic documentation. On that note: I am still using the Classic flavor of OpenAccess; is that a problem?

    My base-class is abstract, but a quick recompile after removing the "abstract"-keyword shows now immediate problems. I think I'll be able to live quite happily with a non-abstract base class...

    Regards,
    Sverre H.
  5. Sverre
    Sverre avatar
    19 posts
    Member since:
    Sep 2008

    Posted 25 Nov 2012 Link to this post

    During the weekend I have actually started converting the project to using the Fluent API. I had been postponing that for quite a wile, so I gave it a try...
    I didn't run into any major problems so far, so hopefully; any tips you can give on the original problem should be based on the new platform...

    Regards,
    Sverre H.
  6. Alexander
    Admin
    Alexander avatar
    727 posts

    Posted 27 Nov 2012 Link to this post

    Hello Sverre,

    We are glad to see that the transition to fluent API has been smooth so far.

    Regarding the linq issue, it seems at the moment there is no perfect solution. Here is a workaround that you could use until we provide better support for this scenario:
    DBContext context = new DBContext();
    Type[] types = new Type[] { typeof(MySubClass1), typeof(MySubClass3) };
     
    Expression<Func<MyBaseClass, bool>> predicate = p => false;
    if(types.Contains(typeof(MySubClass1)))
    {
        Expression<Func<MyBaseClass, bool>> filter = p => p is MySubClass1;
        predicate = Expression.Lambda<Func<MyBaseClass, bool>>(Expression.Or(predicate.Body, filter.Body), predicate.Parameters);
    }
    if (types.Contains(typeof(MySubClass2)))
    {
        Expression<Func<MyBaseClass, bool>> filter = p => p is MySubClass2;
        predicate = Expression.Lambda<Func<MyBaseClass, bool>>(Expression.Or(predicate.Body, filter.Body), predicate.Parameters);
    }
    if (types.Contains(typeof(MySubClass3)))
    {
        Expression<Func<MyBaseClass, bool>> filter = p => p is MySubClass3;
        predicate = Expression.Lambda<Func<MyBaseClass, bool>>(Expression.Or(predicate.Body, filter.Body), predicate.Parameters);
    }
    //And so on for each derived type
     
    var query = context.MyBaseClasses.Where(predicate);
     
    string sql = query.ToString();
    var result = query.ToList();

    The problem currently is that the type we are comparing the "p" lambda parameter to, should be a constant value, not another parameter. This prevents us from using a loop to iterate through the types collection and compose the predicate without using any hardcoded types.
    We will add an entry to our backlog system to improve the support for such queries.

    Please give this a try and let us know if it helps.

    All the best,
    Alexander
    the Telerik team
    Telerik OpenAccess ORM Meets ASP.NET Web API. Read more.
  7. Sverre
    Sverre avatar
    19 posts
    Member since:
    Sep 2008

    Posted 27 Nov 2012 Link to this post

    Hi Alexander!

    I've tested your solution, and it seems to work quite good. I like the fact that it produces a single query to the DB, even if it is a mouthful... We'll just have to wait and see how well it works in production, performance vice...

    I'm pleased to hear that you will investigate better solutions in the future, and I am looking forward to that...

    Thanks again for good service, as always...

    Regards
    Sverre H.
Back to Top
DevCraft banner