.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.