Reputation: 3472
I have a text field on my screen where users can search for a few things from one input field:
What is the best way to write a query that will query these columns?
How should I take the input in, should I split string on space? or comma?
User input = 67 pottors lane 99
where "67 pottors lane" is address
"99" is/could be ID
What I have so far:
//q = querystring
//filteredlist = extension method for the table that I am querying
//clientlist = list of clients I have passed in as a param
//Here is my query for
if (!string.IsNullOrEmpty(q))
{
var result = q.Trim();
filteredlist = filteredlist
.Where(x => x.ID.Contains(q) || x.SubjectPropertyAddress1.Contains(q)
|| x.SubjectPropertyPostCode.Contains(q)
|| clientlist.Any(y=> x.ClientID == y.ClientID && (y.ID.Contains(q) || y.Name.Contains(q)) ));
}
NOTE: I will make use of indexing using sql.
Upvotes: 0
Views: 1156
Reputation: 8920
Perhaps an idea: make an extra column in your database with all the columns you want to search for as one big concattenated string. Then do a free text search of your input string versus that field in the DB.
Since L2SQL does not support free text search, you need to do it in stored procedure in that case or do like here (http://stackoverflow.com/questions/67706/linqtosql-and-full-text-search-can-it-be-done)
Upvotes: 1
Reputation: 1046
I have done a very similar thing in the past. I split the search string on the space character and restricted it to a maximum of 6 search "words", so that the linq is still manageable.
I came up with something like the following:
string[] words = q.ToLower().Split(' ');
string[] wordsFixed = new string[] {"", "", "", "", "", "" };
for(int i = 0; i < 6 && i < words.Length; i++)
wordsFixed[i] = words[i];
var data = from item in list
where (item.ID + item.Name + item.Address1 + item.Address2 + item.PostCode).ToLower().Contains(wordsFixed[0]) &&
(item.ID + item.Name + item.Address1 + item.Address2 + item.PostCode).ToLower().Contains(wordsFixed[1]) &&
(item.ID + item.Name + item.Address1 + item.Address2 + item.PostCode).ToLower().Contains(wordsFixed[2]) &&
(item.ID + item.Name + item.Address1 + item.Address2 + item.PostCode).ToLower().Contains(wordsFixed[3]) &&
(item.ID + item.Name + item.Address1 + item.Address2 + item.PostCode).ToLower().Contains(wordsFixed[4]) &&
(item.ID + item.Name + item.Address1 + item.Address2 + item.PostCode).ToLower().Contains(wordsFixed[5])
select item;
Upvotes: 0
Reputation: 107237
Ouch - is there no way for you to split the input into separate fields for ID, Address, Postcode and Name?
If so, you can keep appending Where clauses, like
var query = filteredList;
if (!String.IsNullOrEmpty(id))
{
query = query.Where(c => c.ID.Contains(id))
}
if (!String.IsNullOrEmpty(name))
{
query = query.Where(c => c.Name.Contains(name))
}
.. same for Name, address etc
Otherwise, your query resembles more of a search engine query than a RDBMS query.
Upvotes: 0