Generics e accesso al database
-
06-07-2019 - |
Domanda
Ho il seguente metodo che posso passare in un'espressione lambda per filtrare il mio risultato e quindi un metodo di callback che funzionerà sull'elenco dei risultati. Questa è solo una tabella particolare nel mio sistema, userò questo costrutto ancora e ancora. Come posso creare un metodo generico, ad esempio DBget che accetta una tabella come parametro (un'entità servizio dati ADO.NET per essere equa) e passare un filtro (un'espansione 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);
}
Il mio primo colpo in questo caso è:
public delegate Action<List<Table>> DBAccess<Table>(Expression<Func<Table, bool>> filter);
Soluzione
Se stai usando Linq per Ado.NET Dataservices o WCF Dataservices, il tuo modello ti costruirà molti tipi. In genere, tuttavia, dovrai selezionare e filtrare. È necessario quanto segue, quindi tutti i tuoi metodi sono solo caramelle sopra questo:
Tipo di query 1 - Un filtro, restituisce un elenco:
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 di query 2 - Un filtro, restituisce una singola entità:
public void makeQuery (entità stringa, filtro espressione >, callback azione) {
IQueryable<T> query = plussContext.CreateQuery<T>(entity).Where(filter);
var DSQuery = (DataServiceQuery<T>)query;
DSQuery.BeginExecute(result =>
{
callback(DSQuery.EndExecute(result).First<T>());
}, null);
}
Quello che devi fare è sovraccaricarli e scambiare il filtro con un semplice array di filtri
Expression<Func<T, bool>>[] filter
E ripeti per i ritorni singoli e di lista.
Raggruppalo in un singleton se vuoi un datacontext, o tieni traccia di una serie di contesti in una sorta di factory / singleton ibrida e sei via. Lascia che il costruttore prenda un contesto o, se non viene fornito, usa il suo e sei via.
Lo uso quindi su una linea larga ma tutto in un unico posto:
GenericQuery.Instance.Create().makeQuery<tblAgencyBranches>("tblAgencyBranches", f => f.tblAgencies.agencyID == _agency.agencyID, res => { AgenciesBranch.ItemsSource = res; });
Questo può sembrare complicato ma nasconde molta magia asincrona e in alcuni casi può essere chiamato direttamente dai gestori dei pulsanti. Non tanto un sistema a 3 livelli, ma un enorme risparmio di tempo.