Linq фильтрует часть даты

#c# #entity-framework #linq

#c# #entity-framework #linq

Вопрос:

У меня есть ввод и таблица данных, когда пользователь вводит этот ввод, я фильтрую данные при вводе ключа в зависимости от того, что ввел пользователь. точно так же, как таблицы данных.net, но это с нуля для обучения.

Таблица данных содержит 3 столбца: полное имя (строка), город (строка) и дата рождения (дата-время).

Я хочу, чтобы, если пользователь введет, например: «2 /», это даст ему все DOB, в которых есть 2 /. пока это мой код (я перепробовал много, но ни один не сработал).

     var data = _context.Person.Where(p => p.DateOfBirth.Value
                       .ToString("d").Split()[0].Contains(SearchQuery)).ToList();
 

// Split(), чтобы удалить временную часть.

И:

 var data = _context.Person.Where(p => p.DateOfBirth.Value
                           .ToString().Contains(SearchQuery)).ToList();
 

Но оба дают мне исключение: «Перевод системы методов.Дата-время.Ошибка toString’

Комментарии:

1. Можете ли вы показать нам определение Person ?

2. Если DateOfBirth используется datetime .Day

3. класс Person { общедоступный длинный идентификатор { get; set; } общедоступная строка Fullname { get; set; } общедоступная дата-время? DateOfBirth { получить; установить; } }

4. Ооо.. Я сомневаюсь, что это сработает хорошо. Я думаю, вам следует уточнить свои требования, а не пытаться закодировать это.. Если пользователь вводит 2/ , и вы хотите вернуть даты рождения, такие как 2002/11/31, 2010/12/31, 2000/2/11, и вы хотите делать это при каждом нажатии клавиши … Тьфу

5. @Charlieface но что, если пользователь продолжит вводить «2/02 /», потому что я как бы показываю данные, пока пользователь печатает.

Ответ №1:

Когда вы используете LINQ-to-entities, ваш код на C # фактически не выполняется. Он анализируется. Среда выполнения проанализирует код C # как выражение и преобразует каждый символ в некоторую часть строки SQL. Затем он отправляет эту строку в базу данных для выполнения на сервере. Сервер не поддерживает те же виды форматирования даты, поэтому выражение вызова вашего метода не поддерживается; нет способа перевести его в строку SQL.

Однако большая проблема здесь заключается в том, что вы не должны обращаться к базе данных при каждом нажатии клавиши; это вызовет проблемы.

Вместо этого обратитесь к базе данных только один раз, при загрузке формы. Кэшируйте список в памяти. Вы можете сделать это, вызвав ToList . Сохраните результаты в переменной-члене.

 List<Person> _data;

void Form_Load(object sender, EventArgs e)
{
    _data = _context.Person.ToList();
}
 

Теперь, когда у вас есть локальная копия, вы можете использовать ее вместо вызова базы данных. И поскольку ваш запрос LINQ не обязательно переводить в инструкцию SQL, вы можете использовать любой метод c #, который вы хотите.

 void SearchQuery_KeyUp(object sender, KeyEventArgs e)
{
     var data = _data.Where(p => p.DateOfBirth.Value
                   .ToString("d").Split()[0].Contains(SearchQuery)).ToList();
     Display(data);
}
 

Ответ №2:

Вы можете использовать LIKE оператор, который приблизится к достижению того, чего вы хотите.

 var data = _context.Person.Where(p => EF.Functions.Like(p.DateOfBirth, $"%{searchquery}%")).ToList();
 

Проблема будет заключаться в том, что если вы сохраняете даты в виде DateTime DateTime2 DateTimeOffset поля или, то их представление в базе данных будет отличаться от введенного вами строкового представления. т. Е. В них, вероятно, не будет ‘/’ (хотя это невозможно сказать, поскольку вы не упоминаете свою базу данныхтехнология).

Ответ №3:

Если вы сначала загружаете таблицу в память, вызывая, например context.person.ToList() , ваш метод должен работать и не должен завершаться преобразованием DateTime в a string .

Я бы предложил следующее:

 _context.Person.ToList().Where(p => p.DateOfBirth.Value
                           .ToString("dd/MM/yyyy").Contains(SearchQuery)).ToList();