Сравнение даты со строкой Entity Framework

1

Предположим, что у меня есть база данных 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: Я не могу выполнить фильтрацию в памяти, эта таблица имеет много тысяч строк.

  • 0
    Вы уверены в своих требованиях? Мне кажется очень опасным полагаться на строковое представление даты. Что, если культура между клиентом и сервером отличается?
  • 0
    Да, я полностью уверен. И я не боюсь проблем, которые могут возникнуть, если культура на сервере и клиенте различна.
Показать ещё 2 комментария
Теги:
sql-server
entity-framework

1 ответ

5
Лучший ответ

Нет простого способа конвертировать 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))
  • 0
    Большое спасибо за решение. Я использовал решение для вычисляемых столбцов.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню