Architettura N-Tier con Service Layer, Business Layer e Entity Framework

Volevo solo un feedback / aiuto sul modo in cui sto architettando la mia applicazione. La mia attuale struttura della soluzione assomiglia a questo:

  • UI (applicazione MVC reale)
  • Core (solo Controller e ViewModels)
  • Servizi
  • BLL
  • Dati (Entity framework DbContext, mappato agli oggetti Dominio)
  • Dominio (oggetti POCO semplici)
  • interfacce

Altre cose

  • Ninject per iniettare DbContext in Controller (per richiesta)
  • AutoMapper per associare oggetti Dominio a ViewModel

Tutti gli assembly hanno un riferimento al progetto Interfaces, che, come suggerisce il nome, non è altro che semplici interfacce (cioè IDbContext, IRepository, ecc.).

Il progetto Servizi “lega” tutto il resto. È l’unico assembly che ha un riferimento diretto al livello di accesso ai dati (Entity Framework).

Ho fornito alcuni codici di seguito:

Un esempio di controller è simile al seguente:

namespace Core.Controllers { public class HomeController : Controller { private IDbContext dbContext; public HomeController(IDbContext dbContext) { this.dbContext = dbContext; } public ActionResult Users() { UserService userService = new UserService(dbContext); var users = userService.GetAllUsers(); return View(Mapper.Map<IEnumerable>(users)); } ... 

La class UserService:

 namespace Services { public class UserService { private readonly IDbContext dbContext; public UserService(IDbContext dbContext) { this.dbContext = dbContext; } public IEnumerable GetAllUsers() { IRepository userRepository = new Repository(dbContext); UserBLL userBLL = new UserBLL(userRepository); return userBLL.GetAllUsers(); } ... 

Infine, la class del livello aziendale:

 namespace BLL { public class UserBLL { private readonly IRepository userRepository; public UserBLL(IRepository userRepository) { this.userRepository = userRepository; } public IEnumerable GetAllUsers() { return userRepository.Get(); } ... 

Sto cercando feedback / modi per migliorare. Ho notato che per le attività di base, i miei metodi del livello di servizio saranno esattamente gli stessi dei metodi del livello aziendale (cioè le funzioni “pass through”). Quello che spero è che questa astrazione sarà utile per attività più complesse che potrebbero richiedere chiamate a più livelli di business. Sarebbe semplicemente meglio includere la business logic nel livello di servizio?

Da una rapida occhiata, non credo che il tuo servizio e controller / core layer debbano avere il contesto db inserito in essi in questo modo. In realtà non dipendono direttamente da esso e farlo in questo modo provoca un accoppiamento non ideale. Il livello principale dovrebbe avere il servizio utente iniettato e il servizio utente e BLL dovrebbero avere il repository iniettato. Il repository dovrebbe avere il dbcontext iniettato dal framework DI e non passato come dipendenza.

Perché stai utilizzando l’iniezione di dipendenza quando crei dipendenze direttamente nel servizio?

 public IEnumerable GetAllUsers() { IRepository userRepository = new Repository(dbContext); UserBLL userBLL = new UserBLL(userRepository); return userBLL.GetAllUsers(); } 

Btw. perché stai usando così tanti strati quando in realtà non fanno nulla? Il codice di esempio mostra solo che l’utilizzo del contesto nel controller direttamente produrrebbe lo stesso risultato senza tre strati inutili del wrapper. Potrebbe essere solo un problema del tuo esempio, ma ogni livello dovrebbe apportare qualche logica aggiuntiva. Se lo usi per chiamare qualcosa sul livello inferiore, probabilmente stai sovrascrivendo il tuo codice. Questa è chiamata architettura della cipolla. Questo è anche un motivo per cui non è una ctriggers pratica aggiungere un livello una volta che ne hai bisogno – non in anticipo.

Si prega di controllare questo: http://www.primaryobjects.com/CMS/Article122.aspx Modello di deposito EF + Modello Unità di lavoro. Per quanto riguarda gli altri livelli, dipende davvero dall’applicazione e da ciò che deve essere realizzato. Si prega di fornire maggiori dettagli su ciò che stai cercando di fare.

Alcuni dei miglioramenti nell’organizzazione dei progetti e nella progettazione degli strati possono essere fatti concentrandosi sul rendere gli oggetti Dominio corretti.

Hai detto di avere oggetti POCO semplici come dominio, ma gli oggetti Dominio dovrebbero essere quelli che hanno tutto lo “stato e il comportamento” dell’azienda. Ciò significa che non è necessario disporre di assembly BLL e Domain separati. Una volta definiti gli oggetti Dominio, EF può essere utilizzato per creare il contesto e le classi di entity framework (che non sono classi di dominio a meno che non vi sia alcun comportamento aggiuntivo rispetto al proprio object di dominio, ma la loro differenza potrebbe essere buona per i requisiti futuri).

Un altro punto minore è che penso che avere interfacce distribuite all’interno del livello Domain and Services sia migliore in termini di comprensione da parte di ogni livello da parte di chiunque.