Mapping del tipo SQL-CLR

In LINQ to SQL viene eseguito il mapping del modello di dati di un database relazionale a un modello a oggetti espresso nel linguaggio di programmazione desiderato. Quando viene eseguita l'applicazione, LINQ to SQL converte in SQL le query LINQ (Language Integrated Query) nel modello a oggetti e le invia al database per l'esecuzione. Quando il database restituisce i risultati, questi vengono nuovamente convertiti da LINQ to SQL in oggetti che è possibile usare nel linguaggio di programmazione desiderato.

Per convertire dati tra il modello a oggetti e il database, è necessario definire un mapping dei tipi. LINQ to SQL usa un mapping dei tipi per associare ogni tipo Common Language Runtime (CLR) a un tipo di SQL Server specifico. È possibile definire mapping dei tipi e altre informazioni sul mapping, ad esempio la struttura del database e le relazioni tra tabelle, nel modello a oggetti con mapping basato sugli attributi. In alternativa, è possibile specificare le informazioni sul mapping al di fuori del modello a oggetti con un file di mapping esterno. Per altre informazioni, vedere Mapping basato su attributi e Mapping esterno.

In questo argomento vengono trattati gli aspetti seguenti:

Mapping dei tipi predefiniti

È possibile creare automaticamente il modello a oggetti o il file di mapping esterno tramite Progettazione relazionale oggetti o lo strumento da riga di comando SQLMetal. I mapping dei tipi predefiniti per questi strumenti definiscono i tipi CLR scelti per il mapping alle colonne nel database di SQL Server. Per altre informazioni sull'uso di questi strumenti, vedere Creazione del modello a oggetti.

È inoltre possibile usare il metodo CreateDatabase per creare un database di SQL Server basato sulle informazioni sul mapping nel modello a oggetti o nel file di mapping esterno. I mapping dei tipi predefiniti per il metodo CreateDatabase definiscono il tipo di colonne di SQL Server create per eseguire il mapping ai tipi CLR nel modello a oggetti. Per altre informazioni, vedere Procedura: Creare un database in modo dinamico.

Matrice del comportamento in fase di esecuzione del mapping dei tipi

Nel diagramma seguente viene illustrato il comportamento previsto in fase di esecuzione dei mapping dei tipi specifici quando i dati vengono recuperati dal o salvati nel database. Ad eccezione della serializzazione, LINQ to SQL non supporta il mapping tra i tipi di dati CLR o SQL Server non specificati in questa matrice. Per altre informazioni sul supporto della serializzazione, vedere Serializzazione binaria.

SQL Server to SQL CLR data type mapping table

Nota

Alcuni mapping dei tipi possono comportare eccezioni di overflow o di perdita di dati durante la conversione da o verso il database.

Mapping personalizzato dei tipi

LINQ to SQL consente di usare altri mapping rispetto ai mapping dei tipi predefiniti usati in Progettazione relazionale oggetti, in SQLMetal e dal metodo CreateDatabase. È possibile creare mapping dei tipi personalizzati specificandoli in modo esplicito in un file DBML. È quindi possibile usare tale file DBML per creare il file di mapping e di codice del modello a oggetti. Per altre informazioni, vedere Mapping del tipo personalizzato SQL-CLR.

Differenze di comportamento tra l'esecuzione CLR e l'esecuzione SQL

A causa di alcune differenze di precisione ed esecuzione tra CLR e SQL Server, è possibile ottenere risultati diversi o riscontrare un comportamento diverso a seconda della posizione in cui vengono eseguiti i calcoli. I calcoli effettuati in query LINQ to SQL vengono effettivamente convertiti in Transact-SQL e quindi eseguiti nel database di SQL Server. I calcoli effettuati al di fuori di query LINQ to SQL vengono eseguiti nel contesto di CLR.

Di seguito vengono illustrate alcune differenze di comportamento tra CLR e SQL Server:

  • In SQL Server alcuni tipi di dati vengono ordinati in modo diverso rispetto a dati del tipo equivalente in CLR. I dati di SQL Server di tipo UNIQUEIDENTIFIER, ad esempio, vengono ordinati in modo diverso dai dati CLR di tipo System.Guid.

  • In SQL Server alcune operazioni di confronto tra stringhe vengono gestite in modo diverso rispetto a CLR. In SQL Server il comportamento del confronto tra stringhe dipende dalle impostazioni delle regole di confronto configurate nel server. Per altre informazioni, vedere Utilizzo delle regole di confronto.

  • SQL Server può restituire valori diversi per alcune funzioni mappate rispetto ai valori restituiti da CLR. Differiscono, ad esempio, le funzioni di uguaglianza, in quanto SQL Server considera uguali due stringhe solo se differiscono nello spazio vuoto iniziale, mentre tali stringhe vengono considerate diverse in CLR.

Mapping dei tipi Enum

LINQ to SQL supporta il mapping del tipo System.Enum CLR ai tipi di SQL Server tramite due modalità diverse:

  • Mapping ai tipi numerici SQL (TINYINT, SMALLINT, INT, BIGINT)

    Quando si esegue il mapping di un tipo System.Enum CLR a un tipo numerico SQL, viene eseguito il mapping del valore intero sottostante del tipo System.Enum CLR al valore della colonna del database di SQL Server. Se, ad esempio, un tipo System.Enum denominato DaysOfWeek contiene un membro denominato Tue con un valore intero sottostante pari a 3, tale membro verrà mappato a un valore del database pari a 3.

  • Mapping ai tipi di testo SQL (CHAR, NCHAR, VARCHAR, NVARCHAR)

    Quando si esegue il mapping di un tipo System.Enum CLR a un tipo di testo SQL, il valore del database SQL viene mappato ai nomi dei membri System.Enum CLR. Se, ad esempio, un tipo System.Enum denominato DaysOfWeek contiene un membro denominato Tue con un valore intero sottostante pari a 3, tale membro verrà mappato a un valore del database pari a Tue.

Nota

Quando si esegue il mapping dei tipi di testo SQL a un tipo System.Enum CLR, includere solo i nomi dei membri Enum nella colonna SQL mappata. Gli altri valori non sono supportati nella colonna SQL mappata a Enum.

Progettazione relazionale oggetti e lo strumento da riga di comando SQLMetal non consentono di eseguire automaticamente il mapping di un tipo SQL a una classe Enum CLR. È necessario configurare in modo esplicito questo mapping personalizzando un file DBML per l'uso da parte di Progettazione relazionale oggetti e SQLMetal. Per altre informazioni sul mapping dei tipi personalizzato, vedere Mapping del tipo personalizzato SQL-CLR.

Poiché una colonna SQL per l'enumerazione è dello stesso tipo di altre colonne numeriche e di testo, questi strumenti non sono in grado di riconoscere la finalità e per impostazione predefinita viene usato il mapping come descritto nelle sezioni Mapping dei tipi numerici e Mapping dei tipi di testo e XML seguenti. Per altre informazioni sulla generazione di codice con il file DBML, vedere Generazione di codice in LINQ to SQL.

Il metodo DataContext.CreateDatabase crea una colonna SQL di tipo numerico per eseguire il mapping di un tipo System.Enum CLR.

Mapping dei tipi numerici

LINQ to SQL consente di eseguire il mapping di molti dei tipi numerici CLR e di SQL Server. La tabella seguente illustra i tipi CLR selezionati da Progettazione relazionale oggetti e da SQLMetal durante la compilazione di un modello a oggetti o del file di mapping esterno basato sul database.

Tipo di SQL Server Mapping dei tipi CLR predefinito usato in Progettazione relazionale oggetti e SQLMetal
BIT System.Boolean
TINYINT System.Int16
INT System.Int32
BIGINT System.Int64
SMALLMONEY System.Decimal
MONEY System.Decimal
DECIMAL System.Decimal
NUMERIC System.Decimal
REAL/FLOAT(24) System.Single
FLOAT/FLOAT(53) System.Double

La tabella seguente illustra i mapping dei tipi predefiniti usati dal metodo DataContext.CreateDatabase per determinare il tipo delle colonne SQL create per il mapping ai tipi CLR definiti nel modello a oggetti o nel file di mapping esterno.

Tipo CLR Tipo di SQL Server predefinito usato da DataContext.CreateDatabase
System.Boolean BIT
System.Byte TINYINT
System.Int16 SMALLINT
System.Int32 INT
System.Int64 BIGINT
System.SByte SMALLINT
System.UInt16 INT
System.UInt32 BIGINT
System.UInt64 DECIMAL(20)
System.Decimal DECIMAL(29,4)
System.Single REAL
System.Double FLOAT

Benché sia possibile scegliere tra molti altri mapping dei tipi numerici, alcuni possono comportare eccezioni di overflow o di perdita di dati durante la conversione da o verso il database. Per altre informazioni, vedere Matrice del comportamento in fase di esecuzione del mapping dei tipi.

Tipi Decimal e Money

La precisione predefinita del tipo DECIMAL di SQL Server (18 cifre decimali a sinistra e a destra del separatore decimale) è di gran lunga inferiore alla precisione del tipo System.Decimal CLR a cui è abbinato per impostazione predefinita. Questa differenza può comportare una perdita di precisione quando si salvano dati nel database. Può tuttavia verificarsi il contrario se il tipo DECIMAL di SQL Server viene configurato con più di 29 cifre di precisione. Quando un tipo DECIMAL di SQL Server viene configurato con una precisione maggiore del tipo System.Decimal CLR, può verificarsi una perdita di precisione durante il recupero di dati dal database.

I tipi MONEY e SMALLMONEY di SQL Server, abbinati anch'essi al tipo System.Decimal CLR per impostazione predefinita, hanno una precisione di gran lunga inferiore, che può comportare eccezioni di overflow o di perdita di dati quando si salvano dati nel database.

Mapping dei tipi di testo e XML

LINQ to SQL consente di eseguire il mapping anche di molti tipi XML e basati su testo. La tabella seguente illustra i tipi CLR selezionati da Progettazione relazionale oggetti e da SQLMetal durante la compilazione di un modello a oggetti o del file di mapping esterno basato sul database.

Tipo di SQL Server Mapping dei tipi CLR predefinito usato in Progettazione relazionale oggetti e SQLMetal
CHAR System.String
NCHAR System.String
VARCHAR System.String
NVARCHAR System.String
TEXT System.String
NTEXT System.String
XML System.Xml.Linq.XElement

La tabella seguente illustra i mapping dei tipi predefiniti usati dal metodo DataContext.CreateDatabase per determinare il tipo delle colonne SQL create per il mapping ai tipi CLR definiti nel modello a oggetti o nel file di mapping esterno.

Tipo CLR Tipo di SQL Server predefinito usato da DataContext.CreateDatabase
System.Char NCHAR(1)
System.String NVARCHAR(4000)
System.Char[] NVARCHAR(4000)
Tipo personalizzato che implementa Parse() e ToString() NVARCHAR(MAX)

Benché sia possibile scegliere tra molti altri mapping dei tipi XML e basati su testo, alcuni possono comportare eccezioni di overflow o di perdita di dati durante la conversione da o verso il database. Per altre informazioni, vedere Matrice del comportamento in fase di esecuzione del mapping dei tipi.

Tipi XML

Il tipo di dati XML di SQL Server è disponibile a partire da Microsoft SQL Server 2005. È possibile eseguire il mapping del tipo di dati XML di SQL Server a XElement, XDocument o String. Se nella colonna sono archiviati frammenti XML che non possono essere letti in XElement, per evitare errori di runtime è necessario eseguire il mapping della colonna a String. Di seguito vengono indicati i frammenti XML di cui è necessario eseguire il mapping a String:

  • Una sequenza di elementi XML

  • Attributi

  • Identificatori pubblici

  • Commenti

Benché sia possibile eseguire il mapping di XElement e XDocument a SQL Server in base a quanto illustrato in Matrice del comportamento in fase di esecuzione del mapping dei tipi, il metodo DataContext.CreateDatabase non dispone di alcun mapping dei tipi di SQL Server predefinito per tali tipi.

Tipi personalizzati

Se una classe implementa Parse() e ToString(), è possibile eseguire il mapping dell'oggetto a qualsiasi tipo di testo SQL, ovvero CHAR, NCHAR, VARCHAR, NVARCHAR, TEXT, NTEXT o XML. L'oggetto viene archiviato nel database inviando il valore restituito da ToString() alla colonna mappata del database. L'oggetto viene ricostruito richiamando Parse() sulla stringa restituita dal database.

Nota

LINQ to SQL non supporta la serializzazione tramite System.Xml.Serialization.IXmlSerializable.

Mapping dei tipi data e ora

LINQ to SQL consente di eseguire il mapping di molti dei tipi data e ora di SQL Server. La tabella seguente illustra i tipi CLR selezionati da Progettazione relazionale oggetti e da SQLMetal durante la compilazione di un modello a oggetti o del file di mapping esterno basato sul database.

Tipo di SQL Server Mapping dei tipi CLR predefinito usato in Progettazione relazionale oggetti e SQLMetal
SMALLDATETIME System.DateTime
DATETIME System.DateTime
DATETIME2 System.DateTime
DATETIMEOFFSET System.DateTimeOffset
DATE System.DateTime
TIME System.TimeSpan

La tabella seguente illustra i mapping dei tipi predefiniti usati dal metodo DataContext.CreateDatabase per determinare il tipo delle colonne SQL create per il mapping ai tipi CLR definiti nel modello a oggetti o nel file di mapping esterno.

Tipo CLR Tipo di SQL Server predefinito usato da DataContext.CreateDatabase
System.DateTime DATETIME
System.DateTimeOffset DATETIMEOFFSET
System.TimeSpan TIME

Benché sia possibile scegliere tra molti altri mapping dei tipi data e ora, alcuni possono comportare eccezioni di overflow o di perdita di dati durante la conversione da o verso il database. Per altre informazioni, vedere Matrice del comportamento in fase di esecuzione del mapping dei tipi.

Nota

I tipi di dati DATETIME2, DATETIMEOFFSET, DATE e TIME di SQL Server sono disponibili a partire da Microsoft SQL Server 2008. LINQ to SQL supporta il mapping a questi nuovi tipi a partire da .NET Framework versione 3.5 SP1.

System.Datetime

L'intervallo e la precisione del tipo System.DateTime CLR sono maggiori dell'intervallo e della precisione del tipo DATETIME di SQL Server, che rappresenta il mapping dei tipi predefiniti per il metodo DataContext.CreateDatabase. Per evitare eccezioni relative a date non incluse nell'intervallo di DATETIME, usare DATETIME2, disponibile a partire da Microsoft SQL Server 2008. DATETIME2può corrispondere all'intervallo e alla precisione del CLR System.DateTime.

Le date di SQL Server non includono alcun concetto di TimeZone, una funzionalità ampiamente supportata in CLR. I valori di TimeZone vengono salvati così come sono nel database senza conversione TimeZone, indipendentemente dalle informazioni DateTimeKind originali. Quando i valori di DateTime vengono recuperati dal database, il relativo valore viene caricato così com'è in un oggetto DateTime con un valore DateTimeKind corrispondente a Unspecified. Per altre informazioni sui metodi System.DateTime supportati, vedere Metodi System.DateTime.

System.TimeSpan

Microsoft SQL Server 2008 e .NET Framework 3.5 SP1 consentono di eseguire il mapping del tipo System.TimeSpan CLR al tipo TIME di SQL Server. Vi è tuttavia una notevole differenza tra l'intervallo supportato dal tipo System.TimeSpan CLR e quello supportato dal tipo TIME di SQL Server. Se si esegue il mapping di valori minori di 0 o maggiori delle ore 23.59.59.9999999 al tipo TIME di SQL Server, verranno restituite eccezioni di overflow. Per altre informazioni, vedere Metodi System.TimeSpan.

In Microsoft SQL Server 2000 e SQL Server 2005 non è possibile eseguire il mapping dei campi del database a TimeSpan. Sono tuttavia supportate operazioni su TimeSpan, in quanto è possibile che i valori TimeSpan vengano restituiti da una sottrazione DateTime o vengano introdotti in un'espressione come un valore letterale o una variabile associata.

Mapping dei tipi binari

Vi sono molti tipi di SQL Server di cui è possibile eseguire il mapping al tipo System.Data.Linq.Binary CLR. La tabella seguente illustra i tipi di SQL Server che determinano in Progettazione relazionale oggetti e SQLMetal la definizione di un tipo System.Data.Linq.Binary CLR durante la compilazione di un modello a oggetti o un file di mapping esterno basato sul database.

Tipo di SQL Server Mapping dei tipi CLR predefinito usato in Progettazione relazionale oggetti e SQLMetal
BINARY(50) System.Data.Linq.Binary
VARBINARY(50) System.Data.Linq.Binary
VARBINARY(MAX) System.Data.Linq.Binary
VARBINARY(MAX) con l'attributo FILESTREAM System.Data.Linq.Binary
IMAGE System.Data.Linq.Binary
TIMESTAMP System.Data.Linq.Binary

La tabella seguente illustra i mapping dei tipi predefiniti usati dal metodo DataContext.CreateDatabase per determinare il tipo delle colonne SQL create per il mapping ai tipi CLR definiti nel modello a oggetti o nel file di mapping esterno.

Tipo CLR Tipo di SQL Server predefinito usato da DataContext.CreateDatabase
System.Data.Linq.Binary VARBINARY(MAX)
System.Byte VARBINARY(MAX)
System.Runtime.Serialization.ISerializable VARBINARY(MAX)

Benché sia possibile scegliere tra molti altri mapping dei tipi binari, alcuni possono comportare eccezioni di overflow o di perdita di dati durante la conversione da o verso il database. Per altre informazioni, vedere Matrice del comportamento in fase di esecuzione del mapping dei tipi.

FILESTREAM di SQL Server

L'attributo FILESTREAM per colonne VARBINARY(MAX) è disponibile a partire da Microsoft SQL Server 2008 e può essere mappato con LINQ to SQL a partire da .NET Framework versione 3.5 SP1.

Benché sia possibile eseguire il mapping di colonne VARBINARY(MAX) con l'attributo FILESTREAM a oggetti Binary, il metodo DataContext.CreateDatabase non è in grado di creare automaticamente colonne con l'attributo FILESTREAM. Per ulteriori informazioni su FILESTREAM, vedere Panoramica di FILESTREAM.

Serializzazione binaria

Se una classe implementa l'interfaccia ISerializable, è possibile serializzare un oggetto in qualsiasi campo binario SQL, ad esempio BINARY, VARBINARY o IMAGE. L'oggetto viene serializzato e deserializzato in base alla modalità di implementazione dell'interfaccia ISerializable. Per altre informazioni, vedere Serializzazione binaria.

Mapping di tipi vari

La tabella seguente illustra i mapping dei tipi predefiniti per alcuni tipi vari non inclusi nelle sezioni precedenti. La tabella seguente illustra i tipi CLR selezionati da Progettazione relazionale oggetti e da SQLMetal durante la compilazione di un modello a oggetti o del file di mapping esterno basato sul database.

Tipo di SQL Server Mapping dei tipi CLR predefinito usato in Progettazione relazionale oggetti e SQLMetal
UNIQUEIDENTIFIER System.Guid
SQL_VARIANT System.Object

La tabella seguente illustra i mapping dei tipi predefiniti usati dal metodo DataContext.CreateDatabase per determinare il tipo delle colonne SQL create per il mapping ai tipi CLR definiti nel modello a oggetti o nel file di mapping esterno.

Tipo CLR Tipo di SQL Server predefinito usato da DataContext.CreateDatabase
System.Guid UNIQUEIDENTIFIER
System.Object SQL_VARIANT

LINQ to SQL non supporta altri mapping per tali tipi vari. Per altre informazioni, vedere Matrice del comportamento in fase di esecuzione del mapping dei tipi.

Vedi anche