Posted by Keith Elder | Posted in .Net, Entity Framework, RIA Services, Silverlight | Posted on 04-02-2011
For years as developers we have tried to master CRUD (create, read, update, delete) when it comes to handling data. For the record CRUD is very outdated and actually incorrect. It should be:
C – creating
R – reading
R – reporting
U – updating
D – deleting
S – searching
Remember you heard it hear first. (and I searched for the term and it doesn’t exist in this context)
Today I want to focus on searching within an application. Searching data is one of the things we take for granted but for some reason it is left out of many applications because developers think it is some magical thing that only Google and Bing can do.
The truth is if you have SQL Server you are just a few minutes away from leveraging it as well. Let’s first setup our database to handle what we call “Full-Text Searching”. I’ll show you how to set this up through Microsoft SQL Server Management Studio and then we will write some code leveraging RIA Services and Silverlight to search a TeamMember table in our application.
Setting Up SQL Server for Full Text Searching
Before we can get started we need to setup SQL Server to take advantage of searching. There are numerous articles on how Full-Text search works including the architecture, querying and so on. You should review those as it covers this in more detail. Here is a walk-through on setting this up in SQL Server Management Studio.
Connect to your database and drill down into Storage->Full Text Catalogs. Right click the “Full Text Catalogs” node and press “New Full-Text Catalog”.
Enter the name of your Full-text catalog name. I’m calling mine “TeamMemberSearch”. Set it as the default catalog and take the defaults on “Accent Sensitivity” which indicates whether the catalog is sensitive or insensitive to diacritics.
Double click on your new catalog to open the properties window. There are a lot of things in here such as actions to rebuild the catalog and check on the population status of the index. On the left side we are interested in “Tables/Views”. Click that.
Since the goal for this example is to search in TeamMember data in our Silverlight application let’s add that table to the catalog. All available columns will be checked. Now obviously we are searching “text” so any columns that aren’t text based will not be selected (int, long, boolean, etc).
That’s it, now click OK. Depending on the size of your table you may want to go back to the General properties of the catalog and check on the population status. The table I’m using has about 20,000 rows in it and populates pretty quickly.
We are now done in SQL Server Management Studio and can focus on making the search work in our Silverlight application.
Using RIA Services and Entity Framework with Full-Text Searching
Now to the good part, the coding part. Here is what our front-end Silverlight application looks like and where we want to allow our end-users to search. (more about this application at the bottom)
The idea is simple. As a user types into the “Search Team Members” field we want to display in real-time results from their typing. We need to take what they’ve entered, send that across the wire from the Silverlight application (we’ll use RIA Services), make sure we handle the asynchronous nature to make sure the search is canceled if they type another character before the search returns and then display the results. Got it? Good. Here we go.
Creating Our Model
In this example I have an existing Entity Framework database model. However, I’m not going to use it but I am going to use the data context of Entity Framework because it allows us to write a standard SQL Query and pass it to Entity Framework and wire it up to a model.
I know in the drop down I want to show the picture of the person I’m searching for and some basic information (phone, team, etc). So I’ll account for that in the model.
I’m going to create a POCO object and the only thing different I’m going to do to this is add a “Key” attribute to the Id property of the class.
If you are curious what happens if you leave the [Key] attribute error off, you’ll get this lovely error:
Error 157 The type ‘NilliusFilius.Web.Models.FullTextSearchResult’ cannot be used as type parameter ‘TEntity’ in the generic type or method ‘System.ServiceModel.DomainServices.Client.LoadOperation<TEntity>’. There is no implicit reference conversion from ‘NilliusFilius.Web.Models.FullTextSearchResult’ to ‘System.ServiceModel.DomainServices.Client.Entity’. C:\Dev\NilliusFilius\NilliusFilius\Controls\SearchControl.xaml.cs 45 26 NilliusFilius
You’ll notice the namespace complaining is DomainServices (aka RIA Services) which we will be using next to return this object from a query.
Creating Our Function in RIA Services
While I don’t have time in this article to cover what RIA Services is basically what it does for us is allow us to add functions to handle CRRUDS calls in our application. While we could use something like a plain WCF service, the nice thing about RIA Services is we don’t have to update service references and deal with contracts and all of that. RIA Services will copy our code to our Silverlight application automatically and *just work*.
In our RIA Service we are going to add a function to search team members and have it return an IQuerable<FullTextSearchResult> which is the object we created earlier.
This function takes one parameter which will be what the user is searching for.
Here’s the plan.
- take the input value and split it on spaces
- build up a list of SqlParameter objects we can pass to Entity Framework
- dynamically build a string that will query our Full-Text catalog
- invoke this query through current ObjectContext of EntityFramework using the ExecuteQuery() which will automatically map our FullTextSearchResult object from this dynamic query
Here is the finished function.
Here is what is happening.
The input string is split based on spaces and then a Full-Text query using “CONTAINS” is created starting on line 6.
Next a transaction is started to avoid deadlocks and then our dynamic Full-Text query is executed and mapped to the FullTextSearchResult object and then returned from RIA Services. That is it, we are done with the backend.
Searching in Silverlight
In Silverlight I’ve made a SearchControl.xaml to handle the searching / returning part.
This control has a Popup control that will display when results are returned that also includes a picture of the team member being returned. Here is the XAML.
In the code behind we are going to watch for the TextChanged event to fire and then query through RIA Services. Remember that we need to make sure that as a user is typing we need to cancel a previous query so we do not get any errors. Here’s the code.
On line 3 we make sure the user has entered more than one character in the search box before searching. Next we check to see if the loadOperation is completed or needs to be canceled. Remember we are in the TextChanged event so if a user presses another character while they are searching we don’t want to wait on the previous search to return instead we want it canceled so we can issue another one.
After that we issue the query and tell it to respond to us back on the function searchTeamMembers_Completed. Here is the completed code that runs after the result is returned.
The main thing that happens is we set the searchPopup to open if there are records found, otherwise it will remain closed.
Here’s the pay off and the end result, it works!
I took this a step further and parsed all of the phone numbers out into a varchar column in SQL Server and added that column to the Full-Text catalog so the extensions could also be searched.
And since the About column is indexed anything in a user’s profile works. In my profile I mentioned Deep Fried Bytes (our podcast) so searching for “deep fried” returns my information.
Full-Text searching rocks needless to say. But when leveraging RIA Services, Entity Framework and Silverlight the experience is really nice.
About The Application
By the way, the application called “Johnny” above will be released soon as a full blown open source project so stay tuned. I’ll update this post when the full source code to this project is available.
Until then, happy searching! – The Elder