WCF RIA Services – Dynamically create a criteria on the client-side
Note: This post is based on the WCF RIA Services VS 2008 PDC Beta and VS 2010 Beta 2 preview, changes can be done before the framework hits RTM.
I have seen questions about how to dynamically create search criteria when using WCF RIA Services and LINQ. So this post is about how you can dynamically create a criteria as a string on the client-side and pass it down to the server for execution.
There is a simple way to create a criteria on the client-side by using WCF RIA Services and LINQ and pass it down to the server for execution, here is an example:
var dx = new CustomerDomainService(); EntityQuery<Customer> query = from customer in dx.GetCustomersQuery() where customer.Country == "Sweden" select customer; dx.Load<Customer>(dx.GetCustomersQuery());
The problem with the above code and LINQ is that LINQ is static. So if we need to dynamically create a criteria it will be hard.
If we for example have an advanced search form with several ComboBox(s) and also TextBox(s) etc. we want to create a query based on the user’s inputs. It will require a lot of code if we use LINQ and probably an ugly condition statement. Wouldn’t it be great if we could do something like this:
var dx = new CustomerDomainService(); string criteria = string.Format("Country = {0} and CompanyName = {1}", countryComboBox.SelectedItem, companyNameTextBox.Text); dx.Load<Customer>(dx.GetCustomersQuery(criteria));
The above code will dynamically create a criteria based on the user’s input and pass it to the GetCustomersQuery.
The CustomerDomainService GetCustomers Query method will look something like this:
[EnableClientAccess()] public class DomainService1 : LinqToEntitiesDomainService<NORTHWNDEntities> { public IQueryable<Customer> GetCustomers(string criteria) { return this.ObjectContext.CustomerSet; } }
As you may see the criteria isn’t used in the code, and if we want to use it we need to parse the criteria and that will require a lot of code to create different static LINQ queries based on criteria. But there is a solution, that is the point of this blog post ;)
We can use the LINQ Dynamic Query Library to solve the problem. To use the LINQ Dynamic Query Library we need to add “using System.Linq.Dynamic” namespace to our DomainService (this after we have the LINQ Dynamic Query Library). To get it you can simply downloaded the example Lib from one of the following links:
What I did to make it work was to add the Dynamic.cs (.vb) class from the example to my Web project. Then added the “using System.Linq.Dynamic” to get the extension method added to the Dynamic.cs (.vb) file to the IEnumerable<T> interface.
When this is done we will have an extended version of the Where extension method which will take a criteria as a string and parse it for us to a valid query.
Here is a simple example where I have created a criteria on the client-side as a string and pass it down to the DomainService, where I use the LINQ Dynamic Query Library:
CustomerDomainService.cs
[EnableClientAccess()] public class CustomerDomainService : LinqToEntitiesDomainService<NORTHWNDEntities> { public IQueryable<Customer> GetCustomers(string criteria) { if (!string.IsNullOrEmpty(criteria)) return this.ObjectContext.CustomerSet.Where(criteria, new object[] { }); return this.ObjectContext.CustomerSet; } }
MainPage.xaml.cs
public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); var dx = new CustomerDomainService(); string criteria = "Country = \"Sweden\" and City <> \"Luleå\""; dx.Load<Customer>(dx.GetCustomersQuery(criteria)); customersDataGrid.ItemsSource = dx.Customers; } }
When using the LINQ Dynamic Query Library all strings need to be enclosed by “ “, so that is the reason why you see \”Sweden\”. To make the criteria more interesting I also added that the City property shouldn’t be “Luleå” (Luleå is a city far to the north in Sweden).
The LINQ Dynamic Query Library will also work on Linq To SQL etc.
Summary
By using the LINQ Dynamic Query Library we can now in a easier way dynamically create a criteria based on users options, for example on a advanced search form.
If you want to know when I post a new blog post on my blog etc, you can follow me on twitter: http://www.twitter.com/fredrikn