Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
LINQ to SQL converte gli operatori di query standard in comandi SQL. Il processore di query del database determina la semantica di esecuzione della traduzione SQL.
Gli operatori di query standard vengono definiti in base alle sequenze. Una sequenza viene ordinata e si basa sull'identità di riferimento per ogni elemento della sequenza. Per altre informazioni, vedere Panoramica degli operatori di query standard (C#) o Panoramica degli operatori di query standard (Visual Basic).
SQL gestisce principalmente set di valori non ordinati. L'ordinamento è in genere un'operazione di post-elaborazione specificata in modo esplicito che viene applicata al risultato finale di una query anziché ai risultati intermedi. L'identità è definita dai valori. Per questo motivo, le query SQL vengono comprese per gestire multinsiemi (bags) anziché set.
I paragrafi seguenti descrivono le differenze tra gli operatori di query standard e la relativa conversione SQL per il provider SQL Server per LINQ to SQL.
Supporto dell'operatore
Concat
Il Concat metodo viene definito per i multiset ordinati in cui l'ordine del ricevitore e l'ordine dell'argomento sono gli stessi.
Concat funziona come UNION ALL nei multiset seguiti dall'ordine comune.
Il passaggio finale consiste nell'ordinare in SQL prima che vengano prodotti i risultati. Concat non mantiene l'ordine degli argomenti. Per garantire l'ordinamento appropriato, è necessario ordinare in modo esplicito i risultati di Concat.
Intersezione, Eccetto, Unione
Le metodologie Intersect e Except sono ben definite solo sugli insiemi. La semantica per i multiset non è definita.
Il Union metodo viene definito per i multiset come concatenazione non ordinata dei multiset (in effetti il risultato della clausola UNION ALL in SQL).
Prendi, Salta
Take e Skip metodi sono ben definiti solo con set ordinati. La semantica per set non ordinati o multiset non è definita.
Annotazioni
Take e Skip presentano alcune limitazioni quando vengono usate nelle query su SQL Server 2000. Per altre informazioni, vedere la voce "Skip and Take Exceptions in SQL Server 2000" (Ignora e accetta eccezioni in SQL Server 2000) in Risoluzione dei problemi.
A causa delle limitazioni relative all'ordinamento in SQL, LINQ to SQL tenta di spostare l'ordinamento dell'argomento di questi metodi al risultato del metodo . Si consideri ad esempio la query LINQ to SQL seguente:
var custQuery =
(from cust in db.Customers
where cust.City == "London"
orderby cust.CustomerID
select cust).Skip(1).Take(1);
Dim custQuery = _
From cust In db.Customers _
Where cust.City = "London" _
Order By cust.CustomerID _
Select cust Skip 1 Take 1
Il codice SQL generato sposta l'ordinamento alla fine, come indicato di seguito:
SELECT TOP 1 [t0].[CustomerID], [t0].[CompanyName],
FROM [Customers] AS [t0]
WHERE (NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM (
SELECT TOP 1 [t1].[CustomerID]
FROM [Customers] AS [t1]
WHERE [t1].[City] = @p0
ORDER BY [t1].[CustomerID]
) AS [t2]
WHERE [t0].[CustomerID] = [t2].[CustomerID]
))) AND ([t0].[City] = @p1)
ORDER BY [t0].[CustomerID]
Diventa evidente che tutti gli ordini specificati devono essere coerenti quando Take e Skip vengono concatenati. In caso contrario, i risultati non sono definiti.
Sia Take che Skip sono ben definiti per argomenti integrali costanti non negativi secondo la specifica degli operatori standard di interrogazione.
Operatori senza traduzione
I metodi seguenti non vengono convertiti da LINQ to SQL. Il motivo più comune è la differenza tra più set non ordinati e sequenze.
| Operatori | Motivazione |
|---|---|
| TakeWhile, SkipWhile | Le query SQL operano su più set, non su sequenze.
ORDER BY deve essere l'ultima clausola applicata ai risultati. Per questo motivo, non esiste alcuna traduzione per utilizzo generico per questi due metodi. |
| Reverse | La traduzione di questo metodo è possibile per un set ordinato ma non è attualmente tradotta da LINQ to SQL. |
| Last, LastOrDefault | La traduzione di questi metodi è possibile per un set ordinato ma non è attualmente tradotta da LINQ to SQL. |
| ElementAt, ElementAtOrDefault | Le query SQL operano su più set, non su sequenze indicizzabili. |
| DefaultIfEmpty (overload con arg predefinito) | In generale, non è possibile specificare un valore predefinito per una tupla arbitraria. I valori NULL per le tuple sono possibili in alcuni casi tramite gli outer join. |
Traduzione di espressioni
Nessuna semantica
LINQ to SQL non impone la semantica di confronto di valori null in SQL. Gli operatori di confronto vengono convertiti sintatticamente nei rispettivi equivalenti SQL. Per questo motivo, la semantica riflette la semantica SQL definita dalle impostazioni di connessione o server. Ad esempio, due valori Null sono considerati diversi nelle impostazioni predefinite di SQL Server, ma è possibile modificare le impostazioni per modificare la semantica. LINQ to SQL non considera le impostazioni del server quando converte le query.
Un confronto con il valore letterale Null viene convertito nella versione SQL appropriata (is null o is not null).
Il valore di null nel confronto è definito da SQL Server. LINQ to SQL non modifica le regole di confronto.
Aggregazioni
Il metodo di aggregazione dell'Operatore Query Standard restituisce zero per una sequenza vuota o per una sequenza che contiene solo valori null. In LINQ to SQL la semantica di SQL viene lasciata invariata e Sum restituisce null invece di zero per una sequenza vuota o per una sequenza che contiene solo valori Null.
Le limitazioni di SQL sui risultati intermedi si applicano alle aggregazioni in LINQ to SQL. Il Sum delle quantità di interi a 32 bit non viene calcolato con risultati a 64 bit. L'overflow può verificarsi per una conversione LINQ to SQL di Sum, anche se l'implementazione dell'operatore di query standard non causa un overflow per la sequenza in memoria corrispondente.
Analogamente, la traduzione dei valori interi di LINQ to SQL di Average viene calcolata come un integer, non come un double.
Argomenti entità
LINQ to SQL consente ai tipi di entità di essere utilizzati nei metodi GroupBy e OrderBy. Nella conversione di questi operatori, l'uso di un argomento di un tipo è considerato equivalente a specificare tutti i membri di tale tipo. Ad esempio, il codice seguente è equivalente:
db.Customers.GroupBy(c => c);
db.Customers.GroupBy(c => new { c.CustomerID, c.ContactName });
db.Customers.GroupBy(Function(c) c)
db.Customers.GroupBy(Function(c) New With {c.CustomerID, _
c.ContactName})
Argomenti equivalenti/confrontabili
L'uguaglianza degli argomenti è necessaria nell'implementazione dei metodi seguenti:
LINQ to SQL supporta l'uguaglianza e il confronto per gli argomenti flat , ma non per gli argomenti che sono o contengono sequenze. Un argomento flat è un tipo di cui è possibile eseguire il mapping a una riga SQL. Una proiezione di uno o più tipi di entità determinati staticamente che non contengono una sequenza viene considerata un argomento piatto.
Di seguito sono riportati esempi di argomenti flat:
db.Customers.Select(c => c);
db.Customers.Select(c => new { c.CustomerID, c.City });
db.Orders.Select(o => new { o.OrderID, o.Customer.City });
db.Orders.Select(o => new { o.OrderID, o.Customer });
db.Customers.Select(Function(c) c)
db.Customers.Select(Function(c) New With {c.CustomerID, c.City})
db.Orders.Select(Function(o) New With {o.OrderID, o.Customer.City})
db.Orders.Select(Function(o) New With {o.OrderID, o.Customer})
Di seguito sono riportati esempi di argomenti non flat (gerarchici):
// In the following line, c.Orders is a sequence.
db.Customers.Select(c => new { c.CustomerID, c.Orders });
// In the following line, the result has a sequence.
db.Customers.GroupBy(c => c.City);
' In the following line, c.Orders is a sequence.
db.Customers.Select(Function(c) New With {c.CustomerID, c.Orders})
' In the following line, the result has a sequence.
db.Customers.GroupBy(Function(c) c.City)
Conversione di funzioni di Visual Basic
Le funzioni helper seguenti usate dal compilatore Visual Basic vengono convertite in operatori e funzioni SQL corrispondenti:
CompareStringDateTime.CompareDecimal.CompareIIf (in Microsoft.VisualBasic.Interaction)
Metodi di conversione:
ToBooleanToSByteToByteToCharToCharArrayRankOneToDateToDecimalToDoubleToIntegerToUIntegerToLongToULongToShortToUShortToSingleToString
Supporto dell'ereditarietà
Restrizioni relative al mapping di ereditarietà
Per altre informazioni, vedere Procedura: Eseguire il mapping delle gerarchie di ereditarietà.
Ereditarietà nelle query
I cast C# sono supportati solo in fase di proiezione. I cast usati altrove non vengono tradotti e vengono ignorati. Oltre ai nomi delle funzioni SQL, SQL esegue in realtà solo l'equivalente di Common Language Runtime (CLR). Convert Ovvero, SQL può modificare il valore di un tipo in un altro. Non esiste alcun equivalente del cast CLR perché non esiste alcun concetto di reinterpretazione degli stessi bit come appartenenti a un altro tipo. Ecco perché un cast C# funziona solo in locale. Non è remoto.
Gli operatori is e as e il metodo GetType non sono limitati all'operatore Select. Possono essere usati anche in altri operatori di query.
Supporto di SQL Server 2008
A partire da .NET Framework 3.5 SP1, LINQ to SQL supporta il mapping ai nuovi tipi di data e ora introdotti con SQL Server 2008. Esistono tuttavia alcune limitazioni per gli operatori di query LINQ to SQL che è possibile usare quando si opera su valori mappati a questi nuovi tipi.
Operatori di query non supportati
Gli operatori di query seguenti non sono supportati sui valori mappati ai nuovi tipi di data e ora di SQL Server: DATETIME2, DATE, TIMEe DATETIMEOFFSET.
AggregateAverageLastOrDefaultOfTypeSum
Per ulteriori informazioni sul mapping a questi tipi di data e ora di SQL Server, consultare mappatura dei tipiSQL-CLR.
Supporto di SQL Server 2005
LINQ to SQL non supporta le funzionalità di SQL Server 2005 seguenti:
Procedure memorizzate scritte per SQL CLR.
Tipo definito dall'utente.
Funzionalità di query XML.
Supporto di SQL Server 2000
Le limitazioni seguenti di SQL Server 2000 (rispetto a Microsoft SQL Server 2005) influiscono sul supporto LINQ to SQL.
Operatori Cross Apply e Outer Apply
Questi operatori non sono disponibili in SQL Server 2000. LINQ to SQL tenta una serie di riscritture per sostituirle con join appropriati.
Cross Apply e Outer Apply vengono generati per gli spostamenti tra relazioni. Il set di query per cui tali riscritture sono possibili non è ben definito. Per questo motivo, il set minimo di query supportato per SQL Server 2000 è il set che non comporta lo spostamento tra relazioni.
testo/ntext
I tipi di dati text / ntext non possono essere usati in determinate operazioni di query su varchar(max) / nvarchar(max), supportate da Microsoft SQL Server 2005.
Per questa limitazione non è disponibile alcuna risoluzione. In particolare, non è possibile utilizzare Distinct() su alcun risultato contenente membri mappati su colonne text o ntext.
Comportamento attivato da query nidificate
Il componente di collegamento di SQL Server 2000 (tramite SP4) presenta alcune idiosincrasie che vengono attivate da query annidate. Il set di query SQL che attiva queste idioincrone non è ben definito. Per questo motivo, non è possibile definire il set di query LINQ to SQL che potrebbero causare eccezioni di SQL Server.
Operatori Skip e Take
Take e Skip presentano alcune limitazioni quando vengono usate nelle query su SQL Server 2000. Per altre informazioni, vedere la voce "Skip and Take Exceptions in SQL Server 2000" (Ignora e accetta eccezioni in SQL Server 2000) in Risoluzione dei problemi.
Materializzazione degli oggetti
La materializzazione crea oggetti CLR da righe restituite da una o più query SQL.
Le chiamate seguenti vengono eseguite localmente come parte della materializzazione:
Costruttori
ToStringmetodi nelle proiezioniCast di tipi nelle proiezioni
I metodi che seguono il AsEnumerable metodo vengono eseguiti localmente. Questo metodo non causa l'esecuzione immediata.
È possibile usare un oggetto
structcome tipo restituito di un risultato della query o come membro del tipo di risultato. Le classi devono essere entità. I tipi anonimi vengono materializzati come istanze di classe, ma le strutture denominate (che non sono entità) possono essere usate nella proiezione.Un membro del tipo di ritorno del risultato di una query può essere di tipo IQueryable<T>. Viene materializzata come raccolta locale.
I metodi seguenti determinano la materializzazione immediata della sequenza a cui vengono applicati i metodi: