#c# #linq #razor-pages
#c# #linq #razor-страницы
Вопрос:
Прежде всего, я прошу прощения, если заголовок этого — мусор. Я новичок в C # и ASP, и я даже не уверен, как задать этот вопрос.
Я пытаюсь включить функцию поиска на свою веб-страницу. У меня есть текстовое поле, которое будет принимать поисковый запрос, который хочет пользователь. В раскрывающемся списке будет выбрано, в каком ПОЛЕ таблицы моей базы данных он будет искать. Итак, если есть фамилии и имена, пользователь может выбрать, в каком из них искать. У меня есть свойство с именем searchField{get; set;}, которое будет содержать значение, выбранное пользователем в раскрывающемся списке, но когда я пытаюсь использовать это в своем операторе LINQ вместе с Contains(бла), я получаю сообщение об ошибке.
Я пробовал очень мало, так как я действительно мало знаю о C # или о том, что ошибка даже говорит мне.
файл cshtml
<form>
<p>
<select asp-for="SearchField" class="form-control">
<option value="FirstName">First Name</option>
<option value="LastName">Last Name</option>
<option value="Salary">Salary</option>
<option value="Gender">Gender</option>
<option value="Department">Department</option>
<option value="Location">Location</option>
<option value="Performance">Performance</option>
</select>
Search: <input type="text" asp-for="SearchString" class="form-control" />
<input type="submit" value="Filter" class="form-control" />
</p>
</form>
cs-файл
[BindProperty(SupportsGet = true)]
public string SearchField { get; set; }
public async Task OnGetAsync()
{
var employees = from x in _context.Employee
select x;
if (!string.IsNullOrEmpty(SearchString))
{
employees = employees.Where(x => x.SearchField.Contains(SearchString));
}
Employee = await employees.ToListAsync();
}
Ошибка: объект не содержит определения для ‘Contains’, а самый известный метод расширения перегружает запрос.Содержит ….. требуется приемник типа IQueryable
Комментарии:
1. Здравствуйте, не могли бы вы предоставить
Employee
класс и свойство searchString ?
Ответ №1:
Вы можете использовать отражение в C #, чтобы получить свойство на основе вашего поля поиска и сравнить значение свойства с вашей поисковой строкой. https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection
В вашем случае:
public async Task OnGetAsync()
{
var employees = from x in _context.Employee
select x;
if (!string.IsNullOrEmpty(SearchString))
{
employees = employees.Where(x => x.GetType().GetProperty(SearchField).GetValue(x, null).ToString() == SearchString);
}
Employee = await employees.ToListAsync();
}
Вы также можете использовать String .Содержит следующим образом:
employees = employees.Where(x => x.GetType().GetProperty(SearchField).GetValue(x, null).ToString().Contains(SearchString, StringComparison.InvariantCultureIgnoreCase));
Ответ №2:
Вам нужно динамически создавать дерево выражений, которое будет фильтровать вашу таблицу и возвращать только совпадающие значения.
Вот что вам нужно для строковых свойств (оно намеренно распределено по многим строкам):
// Expression to construct: (Employee parameter) => parameter.GetPropertyValue(searchField).Contains(SearchValue)
var parameter = Expression.Parameter(typeof(Employee));
var employeePropertyValue = Expression.Property(parameter, searchField);
var constainsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var contains = Expression.Call(employeePropertyValue, containsMethod, Expression.Constant(searchString));
var whereCondition = (Expression<Func<Employee, bool>>)Expression.Lambda(contains, parameter);
// filtering
employees = employees.Where(whereCondition);
Для нестроковых свойств вам нужно будет создать разные условия в зависимости от типа свойства (например, свойство Enum будет храниться в базе данных в виде целого числа, поэтому вам нужно преобразовать searchValue в Gender и использовать Expression .Равно)