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

DataFilter for Complex Type

7 Answers 171 Views
DataFilter
This is a migrated thread and some comments may be shown as answers.
Kevin
Top achievements
Rank 1
Kevin asked on 03 Nov 2010, 01:48 AM
Looking for some guidance on how to achieve using the datafilter on a simple complex type, the schema of which is attached to this post as an image.

The basic idea is that a user should be able to search Configurations based on Fields it has defined as a one-to-many relationship.
The fields table basically contains different name/value parameters for a Configuration.  The design of the tables were inspired by the fact that different Configurations might have different parameters defined (otherwise this could all be in one flat table).

What I'd like to do is enable the user to search for Configurations based on parameters.  So perhaps one of the parameters is Age... the user should be able to use the datafilter to say they want to see all the configurations where Age is greater than 25 for example.

The application uses RIA Services and Entity Framework.  I have complete control over the database structure if a better one exists for the optimal solution.

I figured I would ask the experts.  How would you accomplish this?

 

7 Answers, 1 is accepted

Sort by
0
Rossen Hristov
Telerik team
answered on 03 Nov 2010, 11:08 AM
Hello Kevin,

This cannot be done out-of-the box since it involves custom logic.

I believe that the only way to do this would be to use RadDataFilter in its Unbound Mode, i.e. with no source defined. When in Unbound Mode, you manually specify what the control will show in its UI, i.e. the names of some properties. They do not have to be real properties though.

Then you attach to the events of its FilterDescriptors property (CollectionChanged and ItemChanged) and perform a custom filtering on anything in the world that you like. In fact, the information inside this FilterDescriptors collection is what the user has defined through the UI and can be used for any purpose. Which in your case would be to search through these configuration objects.

If you want to use the Unbound Mode, you have to wait a week or so for the official Q3 release. There will be an example that demonstrates how to use the ItemPropertyDefinitions (the things you add in order to specify what will be shown in the drop-downs) of RadDataFilter.

Once you upgrade to Q3, let me know if you have problems with the Unbound Mode and we will think of something.

Greetings,
Ross
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
0
Kevin
Top achievements
Rank 1
answered on 24 Jul 2011, 09:56 PM
Finally starting to implement the feature I was asking about above, and have more questions.

I understand using the datafilter in the unbound mode.  However, I'm a bit concerned about handling all of the search logic manually.  Is there any mix of controls that might help here?  What I'm asking is, is there any way to use datafilter in unbound mode with a domaindatasource to make the task easier?

I'm just thinking of implementing the custom search logic with all the options presented in datafilter using SQL or LINQ to objects, and it doesn't seem trivial.

If you could nudge me in the right direction here it would be well appreciated.

fyi... I'm using Silverlight, RIA Services, and SQL Azure

Thanks,
KB
0
Rossen Hristov
Telerik team
answered on 25 Jul 2011, 09:14 AM
Hello Kevin,

If you bind RadDataFilter to a RadDomainDataSource, it will automatically "translate" its FilterDescriptors to an EntityQuery<TEntity> and send this filtering info to the server. 

To explore the new RadDomainDataSource control in greater depth, please check its online examples and take a look at the following blog posts:

In case you do not want to use RadDomainDataSource, you will have to write your own logic that takes a collection of FilterDescriptors and translates the information stored in it to your target output format.

In the case of our data engine, we take the FilterDescriptors and we dynamically generate LINQ Lambda Expressions, we compile them at run-time and execute them against the data source, which is usually an IQueryable. In the case of RadDomainDataSource, we take the FilterDescriptors and translate them to an EntityQuery<T>.

So for example, if RadDataFilter has a descriptor which says:

Member=FirstName 
Type=String
Operator=IsEqualTo
Value="John"

we will take it and create something like this:

EntityQuery<Person> query = this.myDomainContext.Persons;
var newQuery = query.Where(person => person.FirstName == "John");

You can write your very own program logic that takes a descriptor and translates it to anything that you need. This will be according to the particular data source that you have.

This entire process is very far from trivial since it involves heavy work with LINQ Expressions and Expression Visitors, but it is not impossible nonetheless.

Or I have another idea, you can read all the data stored in the FilterDescriptors, i.e. Member, Operator, Value and so on, pack it into some kind of comma-delimited long string and pass this huge string as a QueryParemeter of your server-side query method. Then on the server, take the huge string, dis-assemble it, read the filtering info that the user is sending from the client and prepare the respective query against your data source. With this approach you will be performing all the logic on the server, which might be easier form you.

I hope this helps.

Greetings,
Ross
the Telerik team

Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!

0
Kevin
Top achievements
Rank 1
answered on 28 Jul 2011, 02:35 AM
I would actually love to use RadDomainDataSource.  However, I believe you are saying that this is not possible.

Even if I handled the ItemPropertyDefinitions myself, there still seems to be no way to build FilterDescriptors that can be used to query on an associated EntityCollection defined by a one-to-many relationship ( see my data structure in the first post).  While it does seem possible to set the PropertyPath of a FilterDescriptor to search for an associated one-to-one relationship.

Do I have this correct?

If so, I am left with passing something like the FilterDescriptors to the server, and building up my query there.  Would it be possible to share some of the code on how to build up a LINQ query based on your filter descriptors to get me started?  I understand LINQ, but the task seems somewhat daunting at the moment.

0
Kevin
Top achievements
Rank 1
answered on 28 Jul 2011, 05:16 AM
Another question... is there any way to pass a collection of FilterDescriptors to a QueryableDomainServiceCollectionView, and have it return a LINQ Expression?  

At least that would save a ton of time...
0
Rossen Hristov
Telerik team
answered on 28 Jul 2011, 06:41 AM
Hi Kevin,

You are right. RDDS cannot do such complex custom things.

BUT!

We have publicly exposed our Where methods. Here is one of the overloads (in Telerik.Windows.Data.QueryableExtensions):

public static IQueryable Where(this IQueryable source, CompositeFilterDescriptorCollection filterDescriptors)
{
    if (filterDescriptors.Count() > 0)
    {
        var parameterExpression = Expression.Parameter(source.ElementType, "item");
 
        var expressionBuilder = new FilterDescriptorCollectionExpressionBuilder(parameterExpression, filterDescriptors);
        expressionBuilder.Options.LiftMemberAccessToNull = source.Provider.IsLinqToObjectsProvider();
 
        var filterLambda = expressionBuilder.CreateFilterExpression();
 
        //TODO: Delegate the entire job to the FilterDescriptorCollectionExpressionBuilder just like the Sort is implemented.
        if (filterLambda != null)
        {
            return source.Where(filterLambda);
        }
    }
 
    return source;
}

So here is what this method does. You supply an IQueryable and a collection of FilterDescriptors. It takes this collection and based on it appends one or more Where method calls on the IQueryable and then returns it. 

So the easiest way for you would be to provide some kind of dummy (that is -- hollow, doing nothing) IQueryable to this method along with the FilterDescriptors and let it "do its thing" over this IQueryable. Then you can take this resulting IQueryable and read its Expression property. This is the LINQ Expression that our data engine has generated. The whole purpose of this dummy hollow IQueryable is for our data engine to create its Expression over it. Have in mind though that you might have to make the dummy IQueryable behave like its Provider is LinqToEntities and not LinqToObjects, since the generated expressions are somewhat different. When we detect LinqToObjects we add specials checks for null in all expression since SQL server does not care about nulls, but .NET does.

I checked your account and saw that you have our source code. If you want to delve into what we do to create this expression start with the method that I pasted above and drill down. Basically, the classes that interest you will be all classes inheriting from FilterExpressionBuilder.

But I think that if you use our Where method and get the Expression that would be enough for you.

You can even use Expression Visitors and re-visit the expression that we have generated to suit your particular needs.

I hope this helps. All the best,
Ross
the Telerik team

Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!

0
Swetha
Top achievements
Rank 1
answered on 06 Mar 2013, 05:08 PM
Hi Can you please send the sample code to inherit Where of iqiueryable.

Thank you
Swetha
Tags
DataFilter
Asked by
Kevin
Top achievements
Rank 1
Answers by
Rossen Hristov
Telerik team
Kevin
Top achievements
Rank 1
Swetha
Top achievements
Rank 1
Share this question
or