2010-04-14 19 views
7

lo que es la práctica preferida cuando linq2sql utilizando (en aplicaciones de ASP.NET MVC): para crear "Singleton" para DataContext como:linq2sql: Singleton o el uso, las mejores prácticas

partial class db 
{ 
    static db _db = new db(global::data.Properties.Settings.Default.nanocrmConnectionString, new AttributeMappingSource()); 

    public static db GetInstance() 
    { 
     return _db; 
    } 
} 

o para recuperar nueva instancia cuando que necesitaba dentro using:

using (db _db = new db()) 
{ 
    ... 
} 

el uso de using trae algunas limitaciones en código. entonces prefiero usar singleton one. ¿Es una práctica extraña?

UPD:
explicación de por qué estoy usando Singleton:

public class UserGroupRepository 
{ 
    public static IQueryable<Group> RolesFor(string username) 
    { 
     User user = UserRepository.WithUsername(username); 

     return from g in db.GetInstance().Groups 
       join ug in db.GetInstance().UsersGroups on g.Id equals ug.GroupId 
       where ug.UserId == user.Id 
       select g; 
    } 
} 

tengo este método. debido a que devuelve IQueryable - Puedo continuar compilando la consulta sin que se ejecute, por lo que aquí solo devuelve el resultado diferido.
si reescribo el mismo código con using - no puedo devolver IQueryable (porque db se eliminará e IQueryable también se perderá), y lo cambiaría a List. y ahora este método devolverá una "enorme" lista desde la cual filtraré los datos en la función anterior.

espero que describa lo suficientemente detallado.

+0

por curiosidad, ¿qué limitaciones crea el uso de "usar"? Tal vez hay un buen modo de eludirlos ... – LorenVS

+0

@LorenVS: apuesto a que las "limitaciones" se deben a que soy novato, así que creo que hay una solución elegante con 'using' también ;-) – zerkms

+0

Se ha agregado una edición a mi publicación con respecto a su actualización – LorenVS

Respuesta

5

Los contextos de datos de Lqq a Sql NO son seguros para subprocesos y solo se deben usar en el contexto de un solo hilo. El uso del patrón singleton no solo es contrario a las prácticas estándar de linq2sql, sino que generará serios problemas si su aplicación se ve afectada por algún tipo de carga grave.

EDIT:

En respuesta a sus limitaciones en cuanto a la usando el bloque, intente poner en práctica el método de RolesFor como un método de extensión:

public static IQueryable<Group> GetUserRoles(this Database db, string username) 
{ 
     return from g in db.GetInstance().Groups 
       join ug in db.GetInstance().UsersGroups on g.Id equals ug.GroupId 
       where ug.UserId == user.Id 
       select g; 
} 

Esto permitiría que llame a su método en el interior un bloque usando desde cualquier lugar:

using(Database db = createContext()) 
{ 
    IQueryable<Group> queryable = db.GetUserRoles("MyUsername"); 
    // from here on you can query the queryable object 
    var groups = (from g in queryable 
        where g.Name == "MyRole" 
        select g).ToList(); 
} 

EDIT 2

En respuesta a su comentario sobre la apertura de otra conexión al servidor sql para cada instancia del contexto de datos. La creación de un contexto de datos no abrirá una conexión al servidor sql, pero sí lo hará cada operación real. Independientemente de si crea 1 o 4 datacontexts, si está realizando 4 operaciones en la base de datos, se abrirán 4 sqlconnections. Sin embargo, tenga en cuenta que .NET utiliza un grupo de conexiones de servidor sql, por lo que cada operación no requiere la creación de una SqlConnection completamente nueva, sino solo la recuperación de una existente del grupo de conexiones y la reapertura de la conexión

+0

@LorenVS: agrego ** UPD ** a la pregunta original con explicar por qué pregunté la pregunta. – zerkms

+0

esto funcionará, pero esto desperdicia la clase 'db' y es conceptualmente incorrecto. – zerkms

+1

@zerkms, aclare lo que quiere decir, de qué manera es conceptualmente incorrecto y qué quiere decir con perder la clase de base de datos – LorenVS

0

Es probable que desee administrar la vida útil de su contexto para tener un alcance a una sola solicitud web y tener solo un contexto para la duración de ese ciclo de solicitud web.

Google busca 'web scoped objectcontext' o 'objectcontext lifetime' (o datacontext for l2s).

p. Ej.http://dotnetslackers.com/articles/ado_net/Managing-Entity-Framework-ObjectContext-lifespan-and-scope-in-n-layered-ASP-NET-applications.aspx

En MVC2 puede poner el código de gestión de contexto en su clase de controlador base.

+0

sí, esto funciona también, pero se ve como 'diiiiiiirty hack' – zerkms

+0

No, esta es una práctica común. Consulte también http://stackoverflow.com/questions/196253/linq-to-sql-where-does-your-datacontext-live –

+0

, por lo tanto, si creo un contexto de datos almacenado por solicitud (con el almacenamiento en el diccionario como se describe en "Una instancia de ObjectContext compartida por solicitud HTTP"), ¿cómo se eliminarán más tarde? después de que se sirvió la solicitud de todos HttpContext.Current.Items (o incluso HttpContext) .Current) ¿se recogerá basura automáticamente? – zerkms

2

Linq to SQL quiere que cree un contexto por operación. De hecho, las Opciones de carga de datos solo se pueden configurar para ejecutar la primera consulta, por lo que si desea hacer sugerencias de carga, debe hacerlo de esa manera. Sin embargo, cuando tiene una arquitectura de 3 niveles, se encontrará con el problema de que los objetos de un contexto de datos realmente no pueden trabajar con objetos de un contexto diferente.

Trabajar alrededor de eso es un verdadero dolor, así que simplemente hicimos un contexto por solicitud de material web y un enfoque local de subprocesos para servicios de Windows y similares.

+0

sí, como Hightechrider mencionado anteriormente, http-request-context resolverá el "problema", pero para mí (y apuesto por ti) parece un hack sucio, ¿no? – zerkms

+0

Todavía encuentro el concurso por solicitud algo desagradable, especialmente dada la tendencia de los desarrolladores web a recuperar datos en un asunto asincrónico ... Puede que esa no sea la norma para sus sitios, pero si alguien decide agregar una recuperación asincrónica en el en el futuro, tienes un error de subprocesos múltiples a punto de suceder ... Diría que tu mejor opción en esta situación sería traducir los objetos Linq2Sql en tus propios objetos de negocios ... – LorenVS