2012-02-17 15 views
5

I tienen un método de suministro en DAL:Registros de base de datos de rendimiento de rendimiento utilizando LinqToSql?

public IEnumerable<RecordType> GetRecords() 
{ 
    using (LinqDataContext context = new LinqDataContext()) 
    { 
     var records = context.RecordTable; 

     foreach (RecordType record in records) 
     { 
      yield return record; 
     } 
    } 
} 

El método consumidor utiliza los registros en un bucle foreach. De esta forma quiero guardar el uso de la memoria al no almacenar en caché todos los registros desde RecordTable, ya que LinqToSql usa un DataReader detrás de la escena.

Tengo dos preguntas sobre este escenario: aunque

  1. Es eso cierto que el rendimiento por encima de retorno de ahorro de recursos y funciona más rápido que el almacenamiento en caché todos los registros a una matriz (.ToArray())?

  2. ¿La conexión de datos de forma automática correctamente cerrada (me refiero a la declaración using) si se producirá un error en el interior del foreach bucle del método consume o si el método que consume romperá el bucle foreach en el medio (como el encontrado una registro requerido y break)?

Respuesta

3

En el caso de la ejecución de una consulta básica, que puede trabajar de esa manera (sin duda es posible) - sin embargo, en el caso de consultar un Table<T> desnudo, podría ser que todo buffers primero; quizás puedas intentar consultar el recuento durante la iteración o ejecutar un rastreo. En este caso I sospechoso se almacenará primero.

Re cerrado: que también depende; p Si alguien está usando foreach, entonces sí: desde foreach se deshace de forma explícita el iterador a través finally. ¡Sin embargo! No se garantiza si alguien lo hace, por ejemplo (muy traviesa y laxa):

var iter = yourData.GetEnumerator(); 
if(iter.MoveNext()) { 
    Console.WriteLine(iter.Current.Name); // first record of, say, 20 
} 
// and don't dispose the iterator == bad 

continuación, ya que el iterador no hace una: conseguir dispuesto, b: agotarse, y C: no se bloquea, se no se apagará correctamente (cualquiera de esas 3 condiciones será cerrarlo correctamente). Énfasis: este es un caso patológico: normalmente es razonablemente seguro decir "se cerrará, sí".

Si quieres sin Garantía de amortiguación, tenga en cuenta que "pulcro" tiene que, si se establece buffered-false:

IEnumerable<Customer> customers = connection.Query<Customer>(
     "select * from Customer", buffered: false); 

(que puede también manejar los parámetros, etc.)

3

1) yield no será necesariamente más rápido para obtener todos los valores, pero permitiría que el código para iniciar el manejo de resultados antes de la base de datos ha devuelto todos los resultados. Es decir, yield devuelve el primer resultado en el instante en que aparece, mientras que ToArray() necesita esperar a que aparezcan todos los resultados antes de volver. Por supuesto, si los proveedores subyacentes devuelven todos los resultados a la vez debido al almacenamiento en búfer u otras razones, esto puede no hacer la diferencia.

2) Sí, using dispondrá de la LinqDataContext no importa lo que salga del bloque usando (excepciones/retorno/pausa/...)

+1

En realidad, el 2 es "siempre y cuando la persona que llama se comporta adecuadamente" - no es estrictamente como "garantizada" ya que la mayoría son 'using' –

+0

@MarcGravell Asumo que estás hablando no (correctamente) enumerando el enumerable completo, o ¿me estoy perdiendo algo más? –

+0

sí, caminando manualmente el iterador y haciéndolo incorrectamente. No es un problema cuando se usa 'foreach', que usarán las personas más cuerdas. –

2
  1. El el iterador será evaluado perezosamente. Extraerá el primer elemento y luego lo "cederá" a su consumidor.El impacto en el rendimiento dependerá de cómo se implemente LinqDataContext (puede almacenar cosas en el caché internamente). El uso de ToArray() o ToList() forzará a todos los elementos a salir de LinqDataContext antes de continuar. Por lo tanto, el uso de ToArray() no generará nada hasta que LinqDataContext haya devuelto cada elemento. Si eso es óptimo o no, depende de usted.
  2. Sí, el "uso" se aplicará correctamente.
Cuestiones relacionadas