Могу ли я использовать свойство в предложении LINQ Where?

#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 .Равно)