2010-09-15 7 views
8

He estado codificando con bloques 'using', pero me pregunto si puedo devolver un IQueryable de los siguientes sin que el objeto sea eliminado antes de acceder a él.¿Cómo devuelvo un IQueryable de la consulta Linq a SQL cuando el dbContext está con un bloque 'using'?

public IQueryable<Contact> GetContacts(string clientID) 
{ 
    using (dbDataContext db = new dbDataContext()) 
    { 
     var contacts = from _contacts in db.Contacts 
         where _contacts.ClientID == clientID 
         orderby _contacts.LastName ascending 
         select _contacts; 

     return contacts; 
    } 
} 

hacer yo simplemente retire el bloque de 'utilizar' y vamos .Net administrar los objetos, o puedo obtener LINQ para ejecutar la consulta temprana y devolver el objeto poblada.

+0

tenga en cuenta que no es realmente necesario disponer explícitamente el contexto de datos. buena pregunta, de todos modos. – fearofawhackplanet

+0

@fearofawhackplanet - er, sí lo es. Se debe asumir que cualquier objeto desechable ** requiere ** eliminación, y debe manejarse adecuadamente, IMO. Puede contener una conexión abierta, por ejemplo ... –

+0

@Marc: Estoy siguiendo lo que he leído en varios blogs, y también casi todos los ejemplos de ScottGu y el equipo de Linq. La posición oficial de Microsoft, que yo sepa, es que puedes disponer de ella si te hace sentir mejor, pero en realidad no es necesario. Vea http://leedumond.com/blog/about-disposing-the-datacontext/ como un ejemplo para una discusión sobre el desecho y el problema de ejecución desviada que se describe en esta pregunta. – fearofawhackplanet

Respuesta

6

Si usted no espera a componer aún más los datos (en el DB-servidor), entonces:

return contacts.ToList().AsQueryable(); 

aunque en ese caso preferiría volver IEnumerable<Contact> o IList<Contact> para hacer que la no naturaleza composable obvia. Con el enfoque AsQueryable, seguirá siendo ser composable, pero se compondrá a través de LINQ-to-Objects (entonces después de ha obtenido los registros de la base de datos).

Si hace esperan para componer más, entonces debe pasar los datos de contexto (o, si es posible, una aguas arriba IQueryable<something>) en el método, y dejar que la persona que llama manejar el tiempo de vida:

public IQueryable<Contact> GetContacts(dbDataContext db, string clientID) 
{ 
    return from _contacts in db.Contacts 
      where _contacts.ClientID == clientID 
      orderby _contacts.LastName ascending 
      select _contacts; 
} 
+0

@IckleMonkey - es el tipo * concrete * que más importa, pero una ventaja obvia de 'IList 'es que expondrá' .Count', etc. (y un indexador), haciendo que el acceso sea más conveniente.Pero independientemente de 'IList ' vs 'IEnumerable ', todavía * es * una 'Lista ', por lo que el uso de memoria es independiente. O para una respuesta más concisa: use 'IList ' –

-1

que podría hacer algo como esto

public IQueryable<Contact> GetContacts(string clientID) 
{ 
    IQueryable contacts; 
    using (dbDataContext db = new dbDataContext()) 
    { 
     contacts = from _contacts in db.Contacts 
         where _contacts.ClientID == clientID 
         orderby _contacts.LastName ascending 
         select _contacts; 


    } 

    return contacts; 
} 
+2

Eso no ayudará - la ejecución diferida de consultas LINQ significa que el contexto-db aún se elimina mucho antes de que se llame a 'GetEnumerator()' en la consulta subyacente. Entonces no workee –

0

¿se puede hacer el objeto de contexto una instancia de miembro de su clase? Si puede, aplazará la llamada para ejecutar la consulta hasta que toque realmente el enumerador subyacente a la instancia IQueryable que está devolviendo. Depende de lo que quieras hacer. ¿Necesita devolver IQueryable de este método, o puede arreglárselas con IEnumerable?

+0

Creo que iré con IEnumerable, si uso el método de instancia miembro, entonces puedo encontrarme con el mismo problema si mi clase se usa como un bloque 'using' y quiero acceder a los datos devueltos fuera de este. Gracias por la sugerencia. – polom1nt

0

La instancia del objeto de contacto en el conjunto de resultados IQueryable conservará la referencia del contexto de datos utilizado dentro del bloque de uso y funcionará en el código del cliente de la forma esperada. Podrá realizar operaciones SQL diferidas en la instancia IQueryable resultante y realizar otras operaciones IQueryable normalmente.

+1

Cuando intento, obtengo 'DataContext accedido después de tirar'. – polom1nt

Cuestiones relacionadas