Nella mia esperienza di creazione di applicazioni Web, ho sempre utilizzato un approccio a più livelli. Un DAL che ottiene i dati dal db e popola gli oggetti e BLL che ottiene gli oggetti dal DAL ed esegue qualsiasi logica di business richiesta su di essi e il sito Web che ottiene i dati di visualizzazione dalla BLL. Ho recentemente iniziato a studiare LINQ e la maggior parte degli esempi mostra le query che si verificano direttamente dai code-behind dell'applicazione Web (è possibile che abbia visto solo esempi eccessivamente semplificati). Nelle architetture n-tier, questo è sempre stato visto come un grande no-no.
Sono un po 'incerto su come progettare una nuova applicazione Web. Ho utilizzato Server Explorer e la progettazione dbml in VS2008 per creare le relazioni dbml e oggetto. Mi sembra poco chiaro se il dbml sia considerato il livello DAL, se il sito web deve chiamare metodi all'interno di un BLL, che quindi farebbe le query LINQ, ecc.
Quali sono alcune best practice di architettura generale o approcci a creare una soluzione di applicazione Web utilizzando LINQ to SQL?LINQ alle migliori pratiche per le applicazioni Web SQL
risposta
Ho paura che abbiate davvero visto esempi eccessivamente semplificati. LINQ to SQL (System.Data.Linq) è il tuo livello DAL. Le classi generate da L2S sono il tuo dominio (ma non confondere con Domain-Driven Design). Inoltre, puoi ancora scrivere il tuo Business Layer.
Io cerco sempre di impedire la fuoriuscita del LINQ su SQL DataContext
nel livello di presentazione (la tua app Web). Quindi non dovrebbe essere in grado di creare o impegnare un DataContext
. Né si devono restituire oggetti IQueryable<T>
al livello di presentazione. IMO il livello aziendale dovrebbe avere il pieno controllo sulla durata del DataContext
(unità di lavoro) e la forma delle query SQL.
Tuttavia, ci sono diversi sapori. Alcune persone tentano di rilassare questi vincoli. Altri addirittura vanno molto oltre. Dipende dal tuo gusto e dalle dimensioni dell'applicazione. Più grande è l'applicazione, più è giustificato aggiungere strati di astrazione.
Quando non si consente a IQueryable
s e altri dati correlati di uscire dal livello aziendale, si finiscono per avere alcune sfide interessanti. Ad esempio, il livello di presentazione deve indicare al livello aziendale come ordinare i risultati. Mentre è possibile lasciare che il livello di presentazione ordini i risultati stessi, ciò significherebbe che si dovranno ottenere tutti i dati dal database e dalla pagina al livello di presentazione, cosa che potrebbe portare a un sistema con prestazioni molto scadenti. Esistono diverse soluzioni a questo problema. In tutti i casi dovrai informare il livello aziendale su come ordinare i risultati per te. Le soluzioni possono essere trovate qui in SO quando si cerca LINQ dynamic sort. Ho già scritto una soluzione del genere, here.
Un'altra sfida che non consente di disabilitare IQueryable
s lasciando che BL porti è che anche gli oggetti di dominio spesso non possono lasciare il BL. La maggior parte degli oggetti del dominio LINQ to SQL conterrà proprietà lazy-loaded (ad esempio, raccolte in altri oggetti di dominio). Tuttavia, quando DataContext
ha il controllo del livello aziendale, verrà eliminato, prima di restituire i risultati al livello di presentazione. Quando la presentazione accede a una proprietà lazy loaded, si verificherà un'eccezione, poiché lo DataContext
è già stato eliminato. Quando si smaltisce lo DataContext
nel proprio livello aziendale, questo comportamento è ovviamente "di progettazione".Consentendo al livello di presentazione di ottenere proprietà lazy load significa che BL perde il controllo sulle query che vengono inviate al database, perdendo così il controllo sulle prestazioni.
Per risolvere questo problema, è necessario restituire Data Transfer Objects (DTO) dal BL al livello di presentazione. Un DTO conterrà solo dati e no interno DataContext
e nessuna proprietà caricata pigro. Un DTO può essere formattato appositamente per la richiesta effettiva a portata di mano. Le DTO ovviamente portano alla creazione di codice in testa, quindi la dimensione del sistema e le esigenze di prestazioni devono giustificarlo. Per rendere più facile per me, tendo a mettere i metodi di proiezione statici sul DTO. Anche se questo non è conforme al principio separation of concerns, credo che sia una soluzione molto pratica. Guardiamo ad esempio a questo CustomerDTO:
public class CustomerDTO
{
public int CustomerId { get; set; }
public string Name { get; set; }
// City is flatterned from Address.City.
public string City { get; set; }
internal static IQueryable<CustomerDTO> AsDTO(IQueryable<Customer> customers)
{
return
from customer in customers
select new CustomerDTO()
{
CustomerId = customer.Id,
Name = customer.Name,
City = customer.Address.City
};
}
}
Questa DTO definisce una AsDTO
metodo interno, che è in grado di convertire un insieme di oggetti di dominio Customer
ad una raccolta di CustomerDTO
DTOs. Ciò rende molto più semplice la conversione di oggetti di dominio in DTO. Guardate ad esempio a questo metodo BL:
public static CustomerDTO[] GetCustomersByCountry(string country)
{
using (var db = ContextFactory.CreateContext())
{
IQueryable<Customer> customers =
(from customer in db.Customers
where customer.Address.Country == country
orderby customer.Name, customer.Id);
return CustomerDTO.AsDTO(customers).ToArray();
}
}
La cosa bella di questo approccio è che quando si guarda la query SQL, si vedrà che solo il cliente Id, Nome e la Città del tavolo indirizzo verranno essere recuperato dal database. Questo perché il metodo AsDTO
traduce uno IQueryable
in un altro, consentendo a LINQ di SQL di eseguire l'operazione totale nel database.
Spero che questo dia alcune idee su cosa è possibile fare. Naturalmente, questa è la mia opinione sull'argomento e le cose che ho trovato pratico nelle mie situazioni.
LINQ to SQL è l'accesso DB nell'implementazione DAL, se si desidera separare tra DAL e BLL. Se si dispone di un'applicazione Web meno complessa (e non si intende mai invertire i backend DB), è possibile uscire senza DAL/BLL espliciti e fare tutto ciò che si trova nel codice. LINQ to SQL funziona alla grande per operazioni di sola lettura, ma sembra un po 'più di lavoro per implementare le operazioni di scrittura.
- 1. Configurazione di applicazioni Web asp.net. Le migliori pratiche
- 2. Guida alle migliori pratiche: Swing
- 3. Quali sono i tuoi consigli per le migliori pratiche per la struttura delle applicazioni web?
- 4. Le migliori pratiche per l'interfaccia utente web di selezione multipla?
- 5. Le migliori pratiche per l'organizzazione di query SQL nel codice?
- 6. Le migliori pratiche per l'utilizzo di window.onload
- 7. Migliori pratiche .NET per le connessioni MongoDB?
- 8. Le migliori pratiche per il modello DAO?
- 9. Le migliori pratiche per l'API stored procedure?
- 10. Ansible migliori pratiche per copiare le directory
- 11. Gulpfile.js guardano le migliori pratiche
- 12. Le migliori pratiche per le applicazioni multiforme per mostrare e nascondere i moduli?
- 13. Le migliori pratiche per le bozze di salvataggio automatico?
- 14. Migliori pratiche del sito Web SSL-protected
- 15. Quali sono le migliori pratiche per lo sviluppo di applicazioni semantiche utilizzando Jena & RDF
- 16. Quali sono le migliori pratiche per l'auto aggiornamento di applicazioni PHP + MySQL?
- 17. Le migliori pratiche per le connessioni mobili persistenti su Android?
- 18. Le migliori pratiche per le scritture del database del sito Web durante i backup a freddo?
- 19. Applicazioni pratiche per AtomicInteger
- 20. Quali sono le migliori pratiche per velocizzare l'esecuzione dell'applicazione lucida?
- 21. Le migliori pratiche per gestire le versioni con scons?
- 22. Le migliori pratiche per visualizzare le risorse nidificate in Rails?
- 23. Le migliori pratiche per la distribuzione (php/mysql) all'hosting condiviso?
- 24. Extend app per iPhone 5 - le migliori pratiche
- 25. Le migliori pratiche per estendere gli oggetti in underscore.js
- 26. Le migliori pratiche per la convalida dell'input in ASP.NET?
- 27. Quali sono le migliori pratiche per l'interazione client-server?
- 28. WPF themeing migliori pratiche
- 29. PHP include le migliori pratiche sull'estensione file
- 30. Partecipanti reattivi a Meteor: le migliori pratiche?
grazie per la risposta completa. Mi fa rabbrividire nel fare l'accesso ai dati nel livello di presentazione. Attualmente tendo a fare la maggior parte del mio ordinamento presso il datalayer in modo che non sia un problema. Non ho mai sentito parlare di DTO, sembra qualcosa da approfondire. – derek
Spesso si ritiene che le DTO abbiano un sovraccarico. Sono particolarmente utili quando si inviano dati attraverso il filo (ad esempio, quando si hanno servizi Web WCF o ASMX). Ad esempio, quando leggi "Microsoft.NET: Architecting Applications for the Enterprise" di Dino Esposito, noterai che Dino pensa che di solito generano un sovraccarico quando trasferisci oggetti tra livelli dello stesso AppDomain. Mentre ha ragione su questo, ho comunque trovato che sono utili in quel particolare scenario e vedo il sovraccarico diventare più piccolo quando la tecnologia migliora ... – Steven
Per esempio, i nuovi costrutti di linguaggio C# come le proprietà automatiche rendono più facile la definizione di DTO e un strumento di refactoring come Refactor! Pro consente di generare automaticamente un DTO da una definizione di tipo anonima all'interno di una query LINQ. – Steven