2012-01-31 16 views
7
var queueitem = context.CrawlerQueues. 
       Select(cq => new{cq.Guid,cq.Result}). 
       SingleOrDefault(cq => cq.Guid == guid); 

Está por encima de una mala idea, primero seleccionará todas las filas de la base de datos y luego encontrará una o será inteligente y verá el contexto en el que se usa y solo buscará la fila.Linq, es select(). SingleorDefault() ¿una mala idea?

Motivo para hacer esto es devolver solo los resultados de Guid y Result.

return Newtonsoft.Json.JsonConvert.SerializeObject(queueitem, Formatting.Indented); 

¿Cómo puedo encontrar la respuesta a esto sin tener que controlar el flujo de red o las solicitudes realizadas a la base de datos?

Respuesta

13

"tendrá que seleccionar en primer lugar todas las filas de base de datos y luego encontrar el"

Técnicamente, no, la combinación de .Elija seguido por .SingleOrDefault no va a hacer eso. Select() configura los parámetros para la consulta, pero en realidad no capta ningún dato. La ejecución diferida de LINQ no capta ninguna fila hasta que algo realmente tiene que producir un resultado de datos. Puede redactar varias consultas juntas (.Seleccione (...). Seleccione (..) etc.) y nada realmente capta ninguna fila hasta que realice una operación que devuelva datos, como First() o .ToList().

Sin embargo, el uso de Single() puede hacer que se escanee todo el conjunto de datos para probar que la única fila coincidente es la única fila coincidente.

Piénselo: ¿cómo sabrá la consulta que la fila única es la fila en el conjunto de datos que coincide? Tendrá que tratar de encontrar la siguiente fila. Si realmente hay una sola fila que coincide con millones en el conjunto de datos, Single() puede tener que recorrer todos esos millones de filas para demostrar que la coincidencia actual es la única coincidencia.

Si su conjunto de datos es SQL, y sus datos están indexados de manera que permiten la optimización de consultas, entonces Single() podría no ser tan malo. Pero si sus datos SQL no están indexados de una manera que sea útil para esta consulta, Single() puede crear mucho trabajo para el servidor SQL.

Single() es apropiado si la lógica de su programa realmente necesita saber que la fila devuelta es la única fila en todo el conjunto de datos. Sin embargo, hay otras formas de garantizar la singularidad. Si puede configurar una clave principal en sus datos que coincida con su condición LINQ, entonces solo una fila correspondiente puede existir/agregarse a la base de datos para comenzar, por lo que realmente no necesita Single(). (Y, irónicamente, el rendimiento de Single() también será trivialmente rápido en este caso porque el índice de clave principal se puede usar para optimizar la consulta)

Si solo desea la primera fila que coincida con la condición, use Primero () en lugar de Individual(). Primero() solo tiene que escanear filas de datos hasta que encuentre la primera coincidencia. No tiene que continuar escaneando filas para probar que la primera coincidencia es la única coincidencia, como Single().

+0

Gracias. He estado usando firstordefault pero al hacer la pregunta de alguna manera lo olvidé. –

+0

Iba a sugerir FirstOrDefault() también. –

1

La consulta real ejecutada en realidad depende del proveedor de Linq, pero sí, el proveedor de Linq no evaluará hasta el último momento posible, de modo que conocerá el contexto (SingleOrDefault) antes de ejecutar la consulta. Una buena no buscará nada innecesariamente.

Una buena implementación de Linq realmente traerá 2 filas, ya que SingleOrDefault se ocupa de 3 casos;

  • Sin fila devuelta -> vuelve por defecto
  • Una fila devuelta -> Devuelve la fila
  • más de una fila devuelta -> excepción throw (Secuencia contiene más de un elemento)
2

SingleOrDefault - Devuelve el único elemento de una secuencia, o un valor predeterminado si la secuencia está vacía; este método arroja una excepción si hay más de un elemento en la secuencia.

FirstOrDefault - Devuelve el primer elemento de una secuencia, o un valor predeterminado si la secuencia no contiene elementos.

Semánticamente, quiere FirstorDefault ya que su pregunta menciona que se devolvieron varias filas.

+1

Estás en lo correcto. Pero no fue la pregunta. –

3

Estoy bastante seguro de que esto no devolverá toda la base de datos antes de filtrar, ya que la ejecución de la consulta no se produce hasta que se ejecuta la instrucción 'evaluación', que es SingleOrDefault() en esta consulta.

Si tuviera

context.CrawlerQueues.ToList().Select(cq => new{cq.Guid,cq.Result}).SingleOrDefault(cq => cq.Guid == guid);

esto evaluaría el ToList() antes de filtrar, pero la consulta tal como está es correcta.

Si no está seguro de la ruta de evaluación o el SQL generado a partir de sus declaraciones LINQ, LINQPad es una herramienta muy buena que hace que trabajar con Linq, Linq2Sql, EF sea muy fácil.

Cuestiones relacionadas