Genéricos y acceso a bases de datos
-
06-07-2019 - |
Pregunta
Tengo el siguiente método que puedo pasar en una expresión lambda para filtrar mi resultado y luego un método de devolución de llamada que funcionará en la lista de resultados. Esta es solo una tabla particular en mi sistema, usaré este constructo una y otra vez. ¿Cómo puedo crear un método genérico, por ejemplo, DBget que toma una Tabla como parámetro (una entidad de servicio de datos ADO.NET para ser justo) y pasar un filtro (una expersión de lambda)?
public void getServiceDevelopmentPlan(Expression<Func<tblServiceDevelopmentPlan, bool>> filter, Action<List<tblServiceDevelopmentPlan>> callback)
{
var query = from employerSector in sdContext.tblServiceDevelopmentPlan.Where(filter)
select employerSector;
var DSQuery = (DataServiceQuery<tblServiceDevelopmentPlan>)query;
DSQuery.BeginExecute(result =>
{
callback(DSQuery.EndExecute(result).ToList<tblServiceDevelopmentPlan>());
}, null);
}
Mi primer golpe en esto es:
public delegate Action<List<Table>> DBAccess<Table>(Expression<Func<Table, bool>> filter);
Solución
Si está utilizando Linq to Ado.NET Dataservices o WCF Dataservices, su modelo generará una gran cantidad de tipos escritos. En general, aunque va a seleccionar y filtrar. Necesitas lo siguiente, entonces todos tus métodos son simplemente dulces por encima de esto:
Tipo de consulta 1: un filtro, devuelve una lista:
public void makeQuery<T>(string entity, Expression<Func<T, bool>> filter, Action<List<T>> callback)
{
IQueryable<T> query = plussContext.CreateQuery<T>(entity).Where(filter);
var DSQuery = (DataServiceQuery<T>)query;
DSQuery.BeginExecute(result =>
{
callback(DSQuery.EndExecute(result).ToList<T>());
}, null);
}
Tipo de consulta 2: un filtro, devuelve una sola entidad:
public void makeQuery (entidad de cadena, expresión > filtro, devolución de llamada de acción) {
IQueryable<T> query = plussContext.CreateQuery<T>(entity).Where(filter);
var DSQuery = (DataServiceQuery<T>)query;
DSQuery.BeginExecute(result =>
{
callback(DSQuery.EndExecute(result).First<T>());
}, null);
}
Lo que debes hacer es sobrecargarlos e intercambiar el filtro por una simple variedad de filtros
Expression<Func<T, bool>>[] filter
Y repita para las devoluciones individuales y de lista.
Agrupe esto en un singleton si desea un contexto de datos, o haga un seguimiento de una variedad de contextos en algún tipo de fábrica / singleton híbrido y usted está ausente. Deje que el constructor tome un contexto o si no se proporciona, use el suyo propio y estará fuera.
Luego uso esto en una línea grande pero todo en un solo lugar:
GenericQuery.Instance.Create().makeQuery<tblAgencyBranches>("tblAgencyBranches", f => f.tblAgencies.agencyID == _agency.agencyID, res => { AgenciesBranch.ItemsSource = res; });
Esto puede parecer complicado pero esconde mucha magia asíncrona, y en ciertos casos se puede llamar directamente desde los controladores de botones. No es tanto un sistema de 3 niveles, sino un gran ahorro de tiempo.