2008-10-02 18 views
5

Estoy encontrando algunas peculiaridades con LINQ to SQL.LINQ to SQL Peculiarities

Con una consulta relativamente simple, que desee seleccionar algunos campos, pero tienen los campos de fecha con formato de cadenas, que por primera vez logra así:

 var list = dataContext.MyLists.Single(x => x.ID == myId); 

     var items = from i in list.MyItems 
        select 
         new 
          { 
           i.ID, 
           i.Sector, 
           i.Description, 
           CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "", 
           DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : "" 
          };        

Más tarde probé la siguiente consulta, que es exactamente lo mismo, excepto que estoy preguntando directamente de mi DataContext, en lugar de un elemento en mi primera consulta:

 var items = from i in dataContext.MyLists 
        select 
         new 
          { 
           i.ID, 
           i.Sector, 
           i.Description, 
           CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "", 
           DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : "" 
          }; 

el primero funciona muy bien, pero la segunda consulta produce un:

No se pudo traducir la expresión '...' en SQL y no se pudo tratar como una expresión local.

Si elimino las líneas que dan formato a la fecha, funciona bien. Si elimino la verificación .HasValue, también funciona bien, hasta que haya valores nulos.

¿Alguna idea?

Anthony

+0

Parece que tiene dos consultas totalmente diferentes. Uno es seleccionar de MyItems en un objeto MyList. El segundo es seleccionar de los objetos MyList (no MyItems). ¿Los tipos de datos son los mismos para ambos? Es bastante difícil depurar esto sin saber cuáles son las estructuras de la tabla. – Bryant

Respuesta

14

que haría la parte de SQL sin hacer el formato, y luego hacer el formato en el lado del cliente:

var items = list.MyItems.Select(item => new { item.ID, item.Sector, item.Description, 
               item.CompleteDate, item.DueDate }) 
         .AsEnumerable() // Don't do the next bit in the DB 
         .Select(item => new { item.ID, item.Sector, item.Description, 
               CompleteDate = FormatDate(CompleteDate), 
               DueDate = FormatDate(DueDate) }); 


static string FormatDate(DateTime? date) 
{ 
    return date.HasValue ? date.Value.ToShortDateString() : "" 
} 
+0

Ooooh Me gustó que .AsEnumerable() se dividiera allí. Bonito. – Lucas

+0

Guardado por SO una vez más ... gracias !! –

+0

@Jon Skeet - Te amo. –

8

En la primera consulta, que ya han conseguido los datos desde la base de datos en el momento de la segunda línea funciona (artículos var = ...). Esto significa que la segunda línea se ejecuta en el cliente, donde ToShortDateString puede ejecutarse con bastante felicidad.

En la segunda consulta, porque la selección se ejecuta directamente en una colección IQueryable (dataContext.MyLists), intenta traducir la selección en SQL para procesarla en el servidor, donde no se entiende ToShortDateString, de ahí el "No se pudo traducir" .. "excepción.

Para comprender esto un poco mejor, realmente necesita entender la diferencia entre IQueryable e IEnumerable, y en qué punto una consulta Linq To Sql deja de ser IQueryable y se convierte en IEnumerable. Hay muchas cosas en la web sobre esto.

Espero que esto ayude,

Paul

6

Al igual que el mensaje de error te dice que la diferencia se debe a lo que se puede hacer a nivel local en forma remota mientras se conecta a SQL.

El código Linq tiene que ser convertido por Linq a SQL en un comando SQL para los datos remotos: todo lo que se tiene que hacer localmente no se puede incluir.

Una vez que lo arrastraste a un objeto local (en el primer ejemplo), ya no usa Linq a SQL, simplemente Linq. En ese punto, usted es libre de realizar manipulaciones locales en él.

2

Quizás hubo un error de copiar y pegar o simplemente un error tipográfico en su muestra. Pero si no, este podría ser el problema ...

En la segunda consulta está consultando una colección de listas, mientras que en la primera pregunta estaba consultando los elementos dentro de una lista. Pero no ha ajustado la consulta para dar cuenta de esta diferencia.

Lo que necesita podría ser esto. Tenga en cuenta las líneas comentadas que no aparecieron en su segunda muestra.

var items = from aList in dataContext.MyLists 
       from i in aList.MyItems // Access the items in a list 
       where aList.ID == myId // Use only the single desired list 
       select 
        new 
         { 
          i.ID, 
          i.Sector, 
          i.Description, 
          CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "", 
          DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : "" 
         };