Использование Linq для ObjectDataSource: Как преобразовать дату и время, используя ToShortTimeString?
-
19-08-2019 - |
Вопрос
Я обращаюсь к бизнес-классу с использованием ObjectDataSource и пытаюсь произвести вывод, который имеет смысл для пользователя. Возвращаемые значения описывают класс (как в классе и обучении, а не как программное обеспечение). Я хотел бы показать время в классе в следующем диапазоне: & Quot; 9: 00 AM - 10:00 AM & Quot;.
Это запрос Linq, который я использую для извлечения данных:
return classQuery.Select(p => new SelectClassData
{
ClassID = p.ClassID,
Title = p.Title,
StartDate = p.StartDate.ToShortDateString(),
EndDate = p.EndDate.ToShortDateString(),
TimeOfClass =
p.StartDate.ToShortTimeString() + " - " +
p.EndDate.ToShortTimeString()
}).ToList();
Как видите, я кодирую время начала и окончания в начальной и конечной датах, даже если они потенциально могут быть в разные даты.
Когда я выполняю этот код, я получаю:
" Не удалось перевести выражение 'p.EndDate.ToShortTimeString ()' в SQL и не удалось обработать его как локальное выражение. "
Я знаю, что проецирую результаты, но, будучи новичком в Linq, я предполагал, что C # вызов ToShortTimeString произошел после проекции. Может кто-нибудь помочь мне понять, как получить строку, которую я ищу?
Решение
Причина в том, что запрос используется в LINQ to SQL. LINQ to SQL обрабатывает запросы как деревья выражений. У него есть сопоставления, определенные для некоторых методов (например, Contains
), но поскольку он на самом деле не выполняет их, он не может работать с произвольными методами. Он анализирует запрос и отправляет его на сервер SQL. Эквивалент запроса будет выполнен как оператор SQL на сервере базы данных, и результат вернется. Проблема в том, что ToShortTimeString()
не имеет эквивалентного перевода SQL в LINQ to SQL. Прием, используемый здесь, заключается в получении данных с сервера SQL и вызове метода на стороне клиента (AsEnumerable
сделает это).
return classQuery.Select(p => new { p.ClassID, p.Title, p.StartDate, p.EndDate })
.AsEnumerable()
.Select(p => new SelectClassData {
ClassID = p.ClassID,
Title = p.Title,
StartDate = p.StartDate.ToShortDateString(),
EndDate = p.EndDate.ToShortDateString(),
TimeOfClass = p.StartDate.ToShortTimeString() + " - " + p.EndDate.ToShortTimeString() })
.ToList();
Другие советы
Мне очень нравится ответ Мехрдада. Это не только решает проблему, но и учит меня кое-чему о Linq. Спасибо!
Тем не менее, я продолжал разбираться с этой проблемой и придумал другой подход, который я опишу здесь на случай, если кто-то, спотыкающийся в этом вопросе, захочет рассмотреть. Мой код Linq to SQL теперь выглядит так:
return classQuery.Select(p => new SelectClassData
{
ClassID = p.ClassID,
Title = p.Title,
sDate = p.StartDate,
eDate = p.EndDate
}).ToList();
Обратите внимание, что sDate и eDate теперь являются объектами DateTime, а не строками. В & Quot; SelectClassData & Quot; объект, я просто изменил объявление, чтобы доступ к переменным StartDate, EndDate и TimeOfClass проходил через средство получения свойства:
public class SelectClassData
{
public int ClassID { get; set; }
public string Title { get; set; }
public DateTime sDate { get; set; }
public DateTime eDate { get; set; }
public string StartDate { get { return GetSDate(); } }
public string EndDate { get { return GetEDate(); } }
public string TimeOfClass { get { return GetTimeOfClass(); } }
protected string GetSDate()
{
return sDate.ToShortDateString();
}
protected string GetEDate()
{
return eDate.ToShortDateString();
}
protected string GetTimeOfClass()
{
return sDate.ToShortTimeString() + " - " + eDate.ToShortTimeString();
}
}
То есть я устанавливаю sDate и eDate через LinqToSql, но выполняю " ToShortTimeString " и " ToShortDateString " преобразовывает после поиска Linq, внедряя его в целевой класс данных.