Предположим, что у меня есть база данных SQL Server и таблица, которая выглядит так:
Id int NOT NULL,
Date date NOT NULL
У меня есть соответствующая структура фреймворка сущности:
public class Bundle
{
public int Id {get; set;}
public DateTime Date {get; set;}
}
Пользователь может ввести строку, которая может быть чем угодно. Мне нужно найти все элементы, где Date или любая часть даты содержит строку, введенную пользователем. Итак, в основном, мне нужно выполнить запрос:
SELECT Id, Date
FROM Bundles
WHERE Date LIKE '%user_query_here%'
Моя первая попытка была
query.Where(b => b.Date.ToShortDateString().Contains(filter.Date))
Это вызывает исключение NotSupportedException, поэтому я пробовал это:
query.Where(b => Convert.ToString(b.Date).Contains(filter.Date));
Обратите внимание, что filter.Date является строкой. Это не структура DateTime.
Это также создает исключение. Итак, мой вопрос заключается в том, как выполнить запрос, написанный выше?
PS: Я не могу выполнить фильтрацию в памяти, эта таблица имеет много тысяч строк.
Нет простого способа конвертировать datetime в строку с l2e, к сожалению.
Вы можете использовать некоторые методы SqlFunctions
SqlFunctions.DatePart
вернет int, представляющий часть даты (год, месяц, день, например).
а также
SqlFunctions.StringConvert
может помочь вам преобразовать int в строку (сначала сбрасывая ее в double), которую вы затем можете объединить.
Что-то вроде
.Where(b => (SqlFunctions.StringConvert((double)SqlFunctions.DatePart("y", b))
+ SqlFunctions.StringConvert((double)SqlFunctions.DatePart("m", b))
//etc.
).Contains(filter.Date)
конечно, это нечитаемо, и на самом деле не удобна для индексирования.
A (намного) проще и чище, если вы работаете с сервером sql, было бы создание и использование вычисленного столбца.
Вы можете создать его так (google, чтобы найти, как это сделать правильно, если вы используете Code First и Migrations)
alter table add StringDate as convert(varchar, [Date], 112)//or another format, this will be yyyymmdd
Если вы сначала используете код, вам нужно будет пометить свойство атрибутом
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
Тогда вы сможете сделать
.Where(b => b.StringDate.Contains(filter.Date))