I strongly recommend you read this classic article: https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/
Your concatenated "{Last}, {First}"
string is a view-level concern and should not be performed inside your database code. Your database and internal model object should store a person's name in some canonical format (such as possibly having separate fields (but all fields should be optional!) for Title, First, Middle, Last, Suffix, and any other appropriate cultural conventions for your locality or business domain needs.
Then use a single search box that supports some kind of field-based search syntax, to allow users to find people by free-text search but also by exact field if they know that they're looking for someone with "John" as their given-name instead of "Johnson" as their family name.
Don't forget to split for terms too. I recommend something like this:
- Given
String input = "O'Brien firstname:John";
:
- Filter out non-word characters (punctuation, etc). Normalize values (e.g.
O'Brien
-> OBrien
), perhaps normalize to SOUNDEX too (SQL Server has SOUNDEX support built-in: https://learn.microsoft.com/en-us/sql/t-sql/functions/soundex-transact-sql?view=sql-server-2017)
- Split into terms:
[ any: "OBrien", firstname: "John" ]
(a simple regular-expression could be used for this)
- Build a Linq query for each term (i.e. adding new
.Where
expressions, note that concatenating .Where
is equivalent to the AND
operator. If you want to use multiple .Where
as an OR
operation you'll need PredicateBuilder
, see here: How to dynamically add OR operator to WHERE clause in LINQ
Something like:
class Term {
String Field;
String Value;
}
String input = "O'Brien firstname:John";
Term[] terms = GetTerms( input ); // returns the array from step 3
IQueryable<Owner> query = db.Owners;
foreach( Term term in terms ) {
switch( term.Field.ToUpperInvariant() ) {
case null:
case "ANY":
query = query.Where( o => o.LastName.Contains( term.Value ) || o.FirstName.Contains( term.Value ) || o.Title.Contains( term.Value ) || o.Suffix.Contains( term.Value ) );
break;
case "FIRST":
query = query.Where( o => o.FirstName.Cotains( term.Value ) );
break;
case "LAST":
query = query.Where( o => o.LastName.Contains( term.Value ) );
break;
case "TITLE":
// et cetera...
}
}
List<Owner> results = query.ToList();