I'm trying to add extension method for IQueryable<T>
in order to attach specific where to IQueryable
.
Assuming user is searching for data with name equal to "Matt"
public IEnumerable<Employees> Search(String name)
{
var qList = _context.Employees;
if(!String.isNullOrEmpty(name))
qList = qList.Where(emp => emp.Name == name);
return qList.ToList();
}
Now if user is searching for data with name that starts with "Matt"
- He will probably try to write something like "Matt%**"
or "Matt*"
in a specific textbox. to predict this I can do:
public IEnumerable<Employees> Search(String name)
{
var qList = _context.Employees;
if(!String.isNullOrEmpty(name))
{
string extractedName = name.Replace("%","").Replace("*","");
if(name.EndsWith("%") || name.EndsWith("*");
qList = qList.Where(emp => emp.Name.StartsWith(extractedName));
}
return qList.ToList();
}
A lot of IF statements will be here to predict all of possibilities but OK. I can do that. but what I don't like is to repeat my code every time I do such feature.
How can i make extension method for
IQueryable<T>
which will do this checks all the time for me?
public static IQueryable<T> MyAdvancedSearch<T>(this IQueryable<T> qList, String searchText)
{
if(!String.isNullOrEmpty(searchText))
/// ... Problem starts here.. because I cannot make this "Where":
qList.Where(prop=>prop.??? == searchText);
/// ... I dont know how to tell my method which field should be filtered
}
UPDATE
I've managed to create a extension method which looks OK:
public static IQueryable<T> Filter<T>(this IQueryable<T> qList, Func<T,string> property, string text )
{
if (!String.IsNullOrEmpty(text))
{
if ((text.StartsWith("%") || text.StartsWith("*")) && (text.EndsWith("*") || text.EndsWith("*")))
qList = qList.Where(e => property(e).Contains(text));
else if (text.StartsWith("%") || text.StartsWith("*"))
qList = qList.Where(e => property(e).EndsWith(text));
else if (text.EndsWith("%") || text.EndsWith("*"))
qList = qList.Where(e => property(e).StartsWith(text));
else
qList = qList.Where(e => property(e) == text);
}
return qList;
}
but when I try to do qList.Tolist() I'm receiving error:
InvalidOperationException: The LINQ expression 'DbSet<Employee>()
.Where(o => Invoke(__property_0, o)
== __text_1)' could not be translated.
InvalidOperationException: The LINQ expression 'DbSet<Employee>() .Where(o => Invoke(__property_0, o) == __text_1)'
could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.
See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
question from:
https://stackoverflow.com/questions/65951293/iqueryablet-extension-method-for-advanced-where