Usando Linq para ObjectDataSource: ¿Cómo transformar datetime usando ToShortTimeString?

StackOverflow https://stackoverflow.com/questions/448890

  •  19-08-2019
  •  | 
  •  

Pregunta

Estoy accediendo a una clase de negocios usando un ObjectDataSource e intento producir resultados que tengan sentido para el usuario. Los valores de retorno describen una clase (como en el aula y la enseñanza, no el software). Me gustaría mostrar la hora de la clase en un rango como este: "9:00 AM - 10:00 AM".

Esta es la consulta Linq que estoy usando para extraer los datos:

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();

Como puede ver, codifico las horas de inicio y finalización en las fechas de inicio y finalización, aunque potencialmente podrían estar en fechas diferentes.

Cuando ejecuto este código obtengo:

" No se pudo traducir la expresión 'p.EndDate.ToShortTimeString ()' a SQL y no se pudo tratar como una expresión local. "

Sé que estoy proyectando los resultados pero, como soy nuevo en Linq, asumí que la llamada de C # a ToShortTimeString ocurrió después de la proyección. ¿Alguien puede ayudarme a descubrir cómo obtener la cadena que estoy buscando?

¿Fue útil?

Solución

El motivo es que la consulta se está utilizando en LINQ to SQL. LINQ to SQL trata las consultas como árboles de expresión. Tiene asignaciones definidas para algunos métodos (por ejemplo, Contiene ) pero como realmente no las ejecuta, no puede funcionar en métodos arbitrarios. Analiza la consulta y la envía al servidor SQL. El equivalente de la consulta se ejecutará como una declaración SQL en el servidor de la base de datos y el resultado volverá. El problema es que ToShortTimeString () no tiene una traducción SQL equivalente en LINQ to SQL. El truco utilizado aquí es obtener datos del servidor SQL y llamar al método en el lado del cliente ( AsEnumerable hará esto).

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();

Otros consejos

Me gusta mucho la respuesta de Mehrdad. No solo resuelve el problema, sino que también me enseña algo sobre Linq. ¡Gracias!

Sin embargo, me he mantenido al margen del problema y se me ocurrió un enfoque diferente que describiré aquí en caso de que alguien más que se tope con esta pregunta quiera considerarlo. Mi código Linq to SQL ahora dice:

return classQuery.Select(p => new SelectClassData
                              {
                                   ClassID = p.ClassID,
                                   Title = p.Title,
                                   sDate = p.StartDate,
                                   eDate = p.EndDate
                              }).ToList();

Tenga en cuenta que sDate y eDate ahora son objetos DateTime en lugar de cadenas. En el " SelectClassData " objeto, simplemente cambié la declaración para que el acceso a las variables StartDate, EndDate y TimeOfClass pase por un captador de propiedades:

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();
    }
}

Es decir, configuro sDate y eDate a través de LinqToSql pero hago el " ToShortTimeString " y "ToShortDateString" transformaciones después de la recuperación de Linq al implementarlo en la clase de datos de destino.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top