62 messaggi dal 22 ottobre 2012
Salve un consiglio se possibile.
Ho strutturato la mia web applications su 4 layers.

- Models
- Data Access Layer and Repositories (Data)
(ha come riferimento Models)
- Service Layer
(ha come riferimento Models e Data)
- Presentation Layer (UI)
(ha come riferimento Models e Data e Service)

Dal layer (UI) dove ci sono controller, view, viewmodel ... ho la necessità di passare come parametro di un metodo della classe "Service" una classe "filter" che contiene dei valori ricavati dal viewmodel.
La classe filter contiene i criteri per eseguire una selezione sui dati.

[HttpPost]
public ActionResult SearchResult(DocTeSearchViewModel vm)
{ .....
DocTes =docteService.GetDocTesFiltered(filter).ToList(); ....


A sua volta nel layer "Service" il metodo "GetDocTesFiltered"

//Filter
public IEnumerable<DocTe> GetDocTesFiltered (filter obj)
{
return DoctesRepository.GetDocTesFiltered(obj);
}

richiama la stessa classe filter.

volevo sapere se questo metodo era corretto e se era corretto creare questa classe nel layer Models visto che è quello visibile da tutti i livelli oppure ....

Grazie
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,

rubinim ha scritto:

volevo sapere se questo metodo era corretto e se era corretto creare questa classe nel layer Models visto che è quello visibile da tutti i livelli

Beh, sì, quella classe deve necessariamente trovarsi in un progetto referenziato sia dalla UI che dal Service, altrimenti la compilazione fallirebbe.

Ora dovrei capire se quella classe contiene proprietà o metodi rilevanti solo per la UI. Ad esempio, se avesse delle dipendenze da System.Web, non sarebbe troppo corretto posizionarla nel progetto Models perché così ne limiterebbe la portabilità (cioè introdurresti dipendenze che non hanno senso in applicazioni non web).

Quel che potresti fare, quindi è inserire nel progetto Model sono un'interfaccia, da chiamare ad esempio IFilter e, a quel punto, i metodi del Service layer accetterebbero argomenti di tipo IFilter.
Nel layer della UI saresti quindi libero di creare varie implementazioni di IFilter e di legarli a doppio filo con la UI, se vuoi.

Qui però il discorso si fa un po' astratto perché non conosco come sono fatti questi filtri e come il service layer va ad usarli.

Potresti anche usare delle Func<entita, bool> (un po' come si usa in Entity Framework e Linq to Objects) anziché costruirti delle nuove classi. Però non so darti un consiglio preciso non conoscendo bene il tuo scenario.

ciao,
Moreno
Modificato da BrightSoul il 03 settembre 2015 22.07 -

Enjoy learning and just keep making
62 messaggi dal 22 ottobre 2012
Grazie per i consigli. In linea generale ho capito quanto scritto, ora vedi quale potrebbe essere la soluzione migliore.

Ciao e Grazie ancora
62 messaggi dal 22 ottobre 2012
Ciao, scusami avresti al possibilità di farmi un'esempio della soluzione creando l'interfaccia IFilter.

Ciao eGrazie in anticipo se possibile.
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao, ecco un esempio di quello che intendevo nel post precedente. Vedi se può adattarsi al tuo caso.
https://dotnetfiddle.net/votdiz

ciao,
Moreno

Enjoy learning and just keep making
62 messaggi dal 22 ottobre 2012
Ciao, un'altro consiglio.
Il metodo che hai indicato da posizionare nel business layer utilizza ... filtro.ApplicaFiltro(clienti).AsEnumerable().

Nella mia applicazione ho il livello service ( business layer ) ma ho anche creato un livello "repositories", ho seguito quanto consigliato in http://chsakell.com/2015/02/15/asp-net-mvc-solution-architecture-best-practices/

dal livello service richiamo i metodi del repositories.
In questo caso è dal livello repository che dovrei richiamare il
filtro.ApplicaFiltro(clienti).AsEnumerable() ?

Service:
//Filter2
public IEnumerable<DocTe> GetDocTesByFilter2(IFilter<DocTe> filtro)
{
return doctesRepository.GetDocTesByFilter2(filtro);
}
Repository:

public IEnumerable<DocTe> GetDocTesByFilter2(IFilter<DocTe> filtro)
{
try
{
return filtro.ApplicaFiltro(DbContext.DocTes).AsEnumerable();
}
catch (Exception e)
{
return null;
}
}
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,


In questo caso è dal livello repository che dovrei richiamare il

Direi di no perché il repository ha una sola responsabilità molto specifica: recuperare entità dallo storage e persisterle quando vuoi salvare i cambiamenti. E' un servizio infrastrutturale che si occupa di traghettare i dati tra il modello relazionale e quello ad oggetti.

Tutte le logiche di filtraggio potresti inserirle nello strato dei servizi applicativi, che contengono invece - tra le altre cose - la logica con cui vai ad interrogare il repository.

Ora c'è un problema da risolvere: l'articolo che hai linkato propone un'implementazione di IRepository che non espone mai degli IQueryable, ma degli IEnumerable. Guarda per esempio la firma del metodo GetAll
// Gets all entities of type T
IEnumerable<T> GetAll();


E questo non ti mette in grado di usare la mia implementazione di IFilter, che invece lavora proprio con degli IQueryable.
public interface IFilter<T>{
  IQueryable<T> ApplicaFiltro(IQueryable<T> collezione);
}


Ora bisogna decidere se preferisci modificare l'implementazione del repository o l'implementazione di IFilter.

Nel primo caso, si tratta di far restituire IQueryable<DocTe> al metodo GetAll(), ammesso che sia possibile. Come stai persistendo i dati nel db? Entity Framework?

Nel secondo caso, bisogna che IFilter esponga una proprietà di tipo Expression<Func<T, bool>> che potrai passare al metodo GetMany del repository.
// Gets entities using delegate
IEnumerable<T> GetMany(Expression<Func<T, bool>> where);

E' abbastanza facile fare questa modifica perché la mia implementazione di IFilter già lavora internamente con Expression<Func<T, bool>> (che è l'espressione di filtraggio) e basta tirarla fuori come vedi qui.
https://dotnetfiddle.net/vjbnjE

ciao,
Moreno
Modificato da BrightSoul il 06 ottobre 2015 20.45 -

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.