This is a migrated thread and some comments may be shown as answers.

Array of Type as Expression parameter

5 Answers 93 Views
LINQ (LINQ specific questions)
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Sverre
Top achievements
Rank 2
Sverre asked on 19 Nov 2012, 11:43 PM
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.

5 Answers, 1 is accepted

Sort by
0
Viktor Zhivkov
Telerik team
answered on 22 Nov 2012, 04:13 PM
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.
0
Sverre
Top achievements
Rank 2
answered on 22 Nov 2012, 09:31 PM
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.
0
Sverre
Top achievements
Rank 2
answered on 26 Nov 2012, 12:56 AM
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.
0
Alexander
Telerik team
answered on 27 Nov 2012, 01:45 PM
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.
0
Sverre
Top achievements
Rank 2
answered on 28 Nov 2012, 01:18 AM
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.
Tags
LINQ (LINQ specific questions)
Asked by
Sverre
Top achievements
Rank 2
Answers by
Viktor Zhivkov
Telerik team
Sverre
Top achievements
Rank 2
Alexander
Telerik team
Share this question
or