tutorial new net for .net vb.net linq-to-sql datacontext

.net - new - LinqToSql declara y ejemplifica las mejores prácticas de DataContext



system linq vb net (5)

Creo que tal vez el verdadero problema es que el User probablemente no sea el lugar adecuado para que un miembro de instancia llame a GetUser .

¿Cuál es la mejor práctica en términos de configuración de mi DataContext para facilitar el acceso en mis clases LinqToSql extendidas?

Por ejemplo, tengo una entidad de "Usuario" en mi dbml y quiero agregar métodos a esa clase de esta manera:

Partial Public Class User Public Function GetUser(ByVal UserID as Integer) as User ''Do Work End Function End Class

Para acceder a mi DataContext tendría que declararlo dentro del método así:

Partial Public Class User Public Function GetUser(ByVal UserID as Integer) as User Dim dc as New MyDataContext() Return (From u in dc.Users Where u.ID = UserID).Single() End Function End Class

Me gustaría no tener que hacer eso por cada método. Normalmente (si no extendiera las clases de dbml de LinqToSql) podría hacer esto:

Partial Public Class User Private dc as MyDataContext Public Sub New() dc = new MyDataContext() End Sub Public Function GetUser(ByVal UserID as Integer) as User Return (From u in dc.Users Where u.ID = UserID).Single() End Function Public Function GetAllUsers() as IEnumerable(Of User) Return From u in dc.Users End Function ''etc... End Class

Esto me permitiría acceder al contexto de datos para cada método sin tener que declararlo nuevamente cada vez. Pero, por supuesto, no puedes hacer eso porque el dbml ya tiene un constructor. Y agregar código en el dbml siempre se sobrescribe si alguna vez cambia algo.

¿Alguien tiene alguna buena idea sobre cómo ahorrarme un código de exceso aquí?

TIA!


Hay un par de formas diferentes en que podrías hacer esto que sería una buena práctica, creo. Primero, podría usar un patrón Repositorio en el que consulte el Repositorio para un objeto, vaya a la base de datos, recupere el objeto, tal vez separándolo del contexto de datos o manteniendo el contexto de datos dependiendo de la implementación del Depósito. y te lo devuelve. Los métodos de fábrica para sus objetos estarían en el Repositorio, no en las entidades mismas. Probablemente usaría reflexiones y genéricos para minimizar el número de métodos que tiene que implementar y mantener su código SECO.

Por otro lado, y la forma en que se pretendía utilizar LINQtoSQL de forma nativa en mi humilde opinión, es crear el contexto de datos para cada conjunto de operaciones de base de datos que pretendas realizar. En esto, la creación del contexto de datos ocurre también fuera de la entidad, generalmente en la clase que está usando las entidades, no en la capa de datos en absoluto. También podría agregar métodos al contexto de datos: haga que su contexto de datos real sea abstracto y herede de él, usando la reflexión nuevamente, para realizar algunas de las funciones de recuperación comunes para que no tenga que repetirlas. Probablemente tengas que usar un patrón de base de datos como ActiveRecords donde las columnas de id siempre tienen el mismo nombre para que esto funcione.

Por otro lado, podrías ver usar nHibernate o Castle''s ActiveRecord en lugar de replicar cualquiera de los anteriores en tu propia solución.


Puede ser más fácil si deja la clase de Usuario solo y permite que el IDE maneje su creación.

A menudo prefiero tener una clase separada para manejar la recuperación de datos. Digamos que lo llamas el UserDataProvider y todas las llamadas para obtener una instancia de Usuario finalmente pasan por esta clase.

El constructor de UserDataProvider podría instanciar una instancia global del objeto de contexto de datos para su reutilización. Se vería algo como esto (en C # y código no probado tan desnudo conmigo):

public class UserDataProvider { private UserDataContext _data = null; public UserDataProvider() { _data = new UserDataContext(); } public User GetUser(int userID) { return _data.Users.FirstOrDefault(u => u.UserID == userID); } }

Alternativamente, puede colocar la inicialización en una propiedad y acceder a esa propiedad para el uso del contexto de datos.

public class UserDataProvider { private UserDataContext _dataContext; private UserDataContext DataContext { get { if (_data == null) _data = new UserDataContext(); return _data; } } public User GetUser(int userID) { return DataContext.Users.FirstOrDefault(u => u.UserID == userID); } }


Primero, ¡asegúrese de que está eliminando su DataContext cuando haya terminado! Puede ser un bastardo pesado ( editar no pesado para crear instancias, pero pesado para mantener si sigues usándolo sin eliminar); no quieres viejos DataContexts en la memoria.

En segundo lugar, el DataContext está destinado a representar una única transacción lógica . Por ejemplo, debe crear uno nuevo cada vez que desee iniciar una nueva transacción y deshacerse de él cuando se complete la transacción. Entonces para sus propósitos, ese es probablemente el alcance del método GetUser . Si tiene una serie de llamadas a DB que deben realizarse como un grupo, todas deben usar el mismo DC antes de deshacerse de él.


Como dijo Rex M , el contexto de datos está destinado a ser instanciado, utilizado y dispuesto para cada transacción lógica. Patrones como este a veces se llaman una "unidad de trabajo".

La forma más común (que yo sepa) de hacer esto es crear una instancia de su contexto de datos en un bloque de uso. No he usado VB por un tiempo, pero debería verse más o menos así:

Using dc As New MyDataContext() user = (From u in dc.Users Where u.ID = UserID).Single() End Using

Esto no solo refuerza el aspecto de una transacción / unidad de trabajo (a través de la forma física del código), sino que asegura la invocación de Dispose () en su contexto de datos cuando termina el bloque.

Vea esta página de MSDN :

En general, una instancia de DataContext está diseñada para durar una "unidad de trabajo", sin embargo, su aplicación define ese término. Un DataContext es liviano y no es costoso de crear. Una aplicación típica de LINQ to SQL crea instancias de DataContext en el ámbito del método o como miembro de clases de corta vida que representan un conjunto lógico de operaciones de base de datos relacionadas.