LINQ to SQL a più livelli con servizi Web
LINQ to SQL è progettato soprattutto per essere utilizzato con il livello intermedio in un livello di accesso ai dati (DAL) a regime di controllo libero ("loosely-coupled"), ad esempio un servizio Web. Se il livello di presentazione è una pagina Web ASP.NET, verrà utilizzato il controllo server Web LinqDataSource per gestire il trasferimento dei dati tra l'interfaccia utente e LINQ to SQL nel livello intermedio. Se il livello di presentazione non è una pagina ASP.NET, sarà necessario eseguire operazioni aggiuntive nel livello intermedio e nel livello di presentazione in modo da gestire la serializzazione e deserializzazione dei dati.
Configurazione di LINQ to SQL nel livello intermedio
In un servizio Web o in un'applicazione a più livelli, il livello intermedio contiene il contesto dati e le classi di entità. È possibile creare manualmente queste classi oppure utilizzando SQLMetal.exe o la Object Relational Designer come descritto in un altro punto della documentazione. In fase di progettazione è possibile rendere le classi di entità serializzabili. Per ulteriori informazioni, vedere Procedura: creare entità serializzabili (LINQ to SQL). Un'altra opzione è creare un set separato di classi che incapsulano i dati da serializzare e quindi proiettare in tali tipi serializzabili quando si restituiscono i dati nelle query LINQ.
Definire quindi l'interfaccia con i metodi che i client chiameranno per recuperare, inserire e aggiornare i dati. I metodi di interfaccia eseguono il wrapping delle query LINQ. È possibile utilizzare qualsiasi tipo di meccanismo di serializzazione per gestire le chiamate al metodo remote e la serializzazione dei dati. L'unico requisito è che se si hanno relazioni cicliche o bidirezionali nel modello a oggetti, come ad esempio tra Customers e Orders nel modello a oggetti standard Northwind, è necessario utilizzare un serializzatore che lo supporti. Windows Communication Foundation (WCF) DataContractSerializer supporta le relazioni bidirezionali mentre la classe XmlSerializer utilizzata con i servizi Web non WCF non prevede tale tipo di supporto. Se si sceglie di utilizzare XmlSerializer, sarà necessario accertarsi che il modello a oggetti non contenga relazioni cicliche.
Per ulteriori informazioni su Windows Communication Foundation, vedere Servizi Windows Communication Foundation e dati WCF in Visual Studio.
Implementare le regole business o un'altra regola specifica del dominio utilizzando le classi e i metodi parziali delle classi DataContext e di entità per effettuare l'hook negli eventi di runtime LINQ to SQL. Per ulteriori informazioni, vedere Implementazione della logica di business (LINQ to SQL).
Definizione dei tipi serializzabili
Il livello client o di presentazione deve avere le definizioni dei tipi per le classi che riceverà dal livello intermedio. Tali tipi possono essere classi di entità o classi speciali che eseguono il wrapping solo di determinati campi delle classi di entità per i servizi remoti. In ogni caso, in LINQ to SQL non è importante il modo in cui il livello di presentazione acquisisce le definizioni dei tipi. Ad esempio, il livello di presentazione può utilizzare WCF per generare automaticamente i tipi o può avere una copia di una DLL in cui vengono definiti tali tipi o ancora può definire versioni dei tipi personalizzate.
Recupero e inserimento dei dati
Il livello intermedio definisce un'interfaccia che specifica il modo in cui il livello di presentazione accede ai dati, ad esempio GetProductByID(int productID) o GetCustomers(). Nel livello intermedio, il corpo del metodo crea in genere una nuova istanza di DataContext ed esegue una query su una o più tabelle. Il livello intermedio restituisce quindi il risultato come IEnumerable<T>, dove T è una classe di entità o un altro tipo utilizzato per la serializzazione. Il livello di presentazione non invia o riceve direttamente le variabili di query dal livello intermedio. I due livelli scambiano valori, oggetti e raccolte di dati concreti. Dopo aver ricevuto una raccolta, il livello di presentazione può utilizzare LINQ to Objects per eseguirne una query, se necessario.
Durante l'inserimento dei dati, il livello di presentazione può costruire un nuovo oggetto e inviarlo al livello intermedio oppure il livello intermedio può costruire l'oggetto in base ai valori forniti dal livello di presentazione. In generale, il recupero e l'inserimento dei dati nelle applicazioni a più livelli non differiscono molto dal processo nelle applicazioni a 2 livelli. Per ulteriori informazioni, vedere Esecuzione di query nel database (LINQ to SQL) e Scrittura e invio di modifiche di dati (LINQ to SQL).
Rilevamento delle modifiche per aggiornamenti ed eliminazioni
LINQ to SQL supporta la concorrenza ottimistica basata sui timestamp (anche denominata RowVersions) e sui valori originali. Se le tabelle di database hanno timestamp, gli aggiornamenti e le eliminazioni richiedono operazioni aggiuntive sul livello intermedio o sul livello della presentazione. Tuttavia, se è necessario utilizzare i valori originali per i controlli di concorrenza ottimistica, il livello di presentazione sarà responsabile del rilevamento e dell'invio di tali valori durante l'aggiornamento poiché le modifiche effettuate alle entità nel livello di presentazione non vengono rilevate nel livello intermedio. Infatti, il recupero originale di un'entità e l'eventuale aggiornamento vengono eseguiti in genere da due istanze completamente separate di DataContext.
Maggiore è il numero delle modifiche effettuate dal livello di presentazione, più sono complessi il rilevamento e l'invio delle modifiche al livello intermedio. L'implementazione di un meccanismo per la comunicazione delle modifiche spetta completamente all'applicazione. È necessario solo fornire a LINQ to SQL i valori originali necessari per i controlli di concorrenza ottimistica.
Per ulteriori informazioni, vedere Recupero dei dati e operazioni CUD in applicazioni a più livelli (LINQ to SQL).