Usando Linq para ObjectDataSource: Como transformar datetime usando ToShortTimeString?

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

  •  19-08-2019
  •  | 
  •  

Pergunta

Eu estou acessando uma classe de negócios usando um ObjectDataSource e tentando produzir uma saída que faz sentido para o usuário. Os valores de retorno descrever uma classe (como na sala de aula e ensino, não de software). Eu gostaria de mostrar o tempo da classe como uma gama assim: "09h00-10:00"

Este é o Linq consulta que estou usando para puxar os dados:

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 você pode ver, eu codificar o início e término nas datas inicial e final, mesmo que estes poderiam ser potencialmente em datas diferentes.

Quando eu executar esse código eu recebo:

"Não foi possível traduzir a expressão 'p.EndDate.ToShortTimeString ()' em SQL e não poderia tratá-lo como uma expressão local."

Eu sei que eu estou projetando os resultados, mas, sendo novo para Linq, eu tinha assumido que o C # chamada para ToShortTimeString aconteceu após a projeção. Alguém pode me ajudar a descobrir como obter a string que estou procurando?

Foi útil?

Solução

A razão é a consulta está sendo usado em LINQ to SQL. LINQ to SQL trata consultas como árvores de expressão. Tem mapeamentos definidos para alguns métodos (por exemplo, Contains) mas desde que realmente não executá-los, ele não pode trabalhar em métodos arbitrários. Ele analisa a consulta e envia-lo para o servidor SQL. O equivalente a consulta será executada como uma instrução SQL no servidor de banco de dados e o resultado vai voltar. O problema é ToShortTimeString() não tem uma tradução SQL equivalente em LINQ to SQL. O truque usado aqui é para buscar dados de servidor SQL e chamar o método no lado do cliente (AsEnumerable vai fazer isso).

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

Outras dicas

Eu gosto de resposta de Mehrdad muito. Ele não só resolve o problema, ele também me ensina algo sobre Linq também. Obrigado!

Eu mantive batendo contra o problema, embora, e veio com uma abordagem diferente, que vou descrever aqui no caso de alguém tropeçar sobre esta questão quer considerar. Meu código SQL Linq agora lê-se:

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

Note que sdate e eDate estão agora DateTime objetos em vez de strings. No objeto "SelectClassData", eu simplesmente mudou a declaração para que o acesso às variáveis ??StartDate, EndDate e TimeOfClass passar por um getter propriedade:

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

Isto é, eu definir o sdate e eDate através da LinqToSql mas fazer o "ToShortTimeString" e transformações "ToShortDateString" após a recuperação Linq, implementando-o na classe de dados de destino.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top