Mapeamento de tipo SQL-CLR

No LINQ to SQL, o modelo de dados de um banco de dados relacional mapeia para um modelo de objeto que é expresso na linguagem de programação de sua escolha. Quando o aplicativo é executado, o LINQ to SQL converte consultas integradas à linguagem no modelo de objeto em SQL e as envia para o banco de dados para execução. Quando o banco de dados retorna os resultados, o LINQ to SQL converte os resultados de volta para os objetos com os quais você pode trabalhar em sua própria linguagem de programação.

Para converter dados entre o modelo de objeto e o banco de dados, um mapeamento de tipo deverá ser definido. O LINQ to SQL usa um mapeamento de tipo para corresponder a cada tipo CLR (Common Language Runtime) com um tipo específico de SQL Server. Você pode definir mapeamentos de tipo e outras informações de mapeamento, como estrutura de banco de dados e relações de tabela, dentro do modelo de objeto com mapeamento baseado em atributos. Como alternativa, você pode especificar as informações de mapeamento fora do modelo de objeto com um arquivo de mapeamento externo. Para obter mais informações, confira Mapeamento baseado em atributo e Mapeamento Externo.

Este tópico aborda os seguintes pontos:

Mapeamento de tipo padrão

Você pode criar o modelo de objeto ou arquivo de mapeamento externo automaticamente com o Object Relational Designer (Designer Relacional de Objetos) ou a ferramenta de linha de comando SQLMetal. Os mapeamentos de tipo padrão para essas ferramentas definem quais tipos CLR são escolhidos para mapear colunas dentro do banco de dados do SQL Server. Para obter mais informações sobre como usar essas ferramentas, confira Como criar o Modelo de Objeto.

Você também pode usar o método CreateDatabase para criar um banco de dados do SQL Server com base nas informações de mapeamento no modelo de objeto ou no arquivo de mapeamento externo. Os mapeamentos de tipo padrão para o método CreateDatabase definem quais tipos de colunas do SQL Server são criados para mapear para os tipos CLR no modelo de objeto. Para obter mais informações, consulte Como criar um banco de dados dinâmico.

Matriz de comportamento em tempo de execução de mapeamento de tipo

O diagrama a seguir mostra o comportamento em tempo de execução esperado de mapeamentos de tipo específico quando os dados são recuperados de ou salvos no banco de dados. Com exceção da serialização, o LINQ to SQL não oferece suporte a mapeamento entre qualquer tipo de dados CLR ou SQL Server que não for especificado nesta matriz. Para saber mais sobre o suporte de serialização, confiraSerialização Binária.

SQL Server to SQL CLR data type mapping table

Observação

Alguns mapeamentos de tipo podem resultar em estouro ou exceções de perda de dados ao converter para ou do banco de dados.

Mapeamento de tipo personalizado

Com o LINQ to SQL, você não está limitado aos mapeamentos de tipo padrão usados pelo Designer Relacional de Objetos, pelo SQLMetal e pelo método CreateDatabase. Você pode criar mapeamentos de tipo personalizados explicitamente especificando-os em um arquivo DBML. Em seguida, você pode usar esse arquivo DBML para criar o código do modelo de objeto e o arquivo de mapeamento. Para obter mais informações, confira Mapeamentos de Tipo Personalizado SQL-CLR.

Diferenças de comportamento entre CLR e a execução de SQL

Devido às diferenças na precisão e na execução entre CLR e SQL Server, você poderá receber resultados diferentes ou observar um comportamento diferente dependendo de onde você executa os cálculos. Os cálculos realizados em consultas LINQ to SQL são realmente convertidos para Transact-SQL e, em seguida, executados no banco de dados do SQL Server. Os cálculos realizados fora das consultas LINQ to SQL são executados dentro do contexto do CLR.

Por exemplo, a seguir estão algumas diferenças de comportamento entre o CLR e o SQL Server:

  • O SQL Server pede alguns tipos de dados de maneira diferente dos dados de tipo equivalente no CLR. Por exemplo, os dados do SQL Server do tipo UNIQUEIDENTIFIER são pedidos de maneira diferente dos dados CLR de tipo System.Guid.

  • O SQL Server manipula algumas operações de comparação de cadeia de caracteres de maneira diferente do que no CLR. No SQL Server, o comportamento de comparação de cadeia de caracteres depende das configurações de ordenação no servidor. Para obter mais informações, confira Como trabalhar com ordenações.

  • O SQL Server pode retornar valores diferentes para algumas funções mapeadas do CLR. Por exemplo, as funções de igualdade serão diferentes porque o SQL Server considera que duas cadeias de caracteres serão iguais se diferirem apenas no espaço em branco à direita, enquanto o CLR não as considera iguais.

Mapeamento enum

O LINQ to SQL dá suporte a mapeamento do tipo System.Enum CLR para tipos do SQL Server de duas maneiras:

  • Mapeamento para tipos numéricos do SQL (TINYINT, SMALLINT, INT, BIGINT)

    Quando você mapeia um tipo System.Enum CLR para um tipo numérico do SQL, mapeia o valor inteiro subjacente do System.Enum CLR para o valor da coluna de banco de dados do SQL Server. Por exemplo, se um System.Enum chamado DaysOfWeek contém um membro chamado Tue com um valor inteiro subjacente de 3, esse membro mapeia para um valor de banco de dados de 3.

  • Mapeamento para tipos de texto do SQL (CHAR, NCHAR, VARCHAR, NVARCHAR)

    Quando você mapeia um tipo System.Enum CLR para um tipo de texto do SQL, o valor do banco de dados SQL é mapeado para os nomes dos membros do System.Enum CLR. Por exemplo, se um System.Enum chamado DaysOfWeek contém um membro chamado Tue com um valor inteiro subjacente de 3, esse membro mapeia para um valor de banco de dados de Tue.

Observação

Ao mapear tipos de texto do SQL para um System.Enum CLR, inclua somente os nomes dos membros do Enum na coluna SQL mapeada. Outros valores não têm suporte na coluna SQL mapeada para Enum.

A ferramenta de linha de comando do Designer Relacional de Objetos e do SQLMetal não pode mapear automaticamente um tipo SQL para uma classe Enum CLR. Você deve configurar explicitamente esse mapeamento personalizando um arquivo DBML para ser usado pelo Designer Relacional de Objetos e pelo SQLMetal. Para obter mais informações sobre o mapeamento de tipo personalizado, confira Mapeamentos de Tipo Personalizado SQL-CLR.

Como uma coluna SQL destinada para enumeração será do mesmo tipo que outras colunas numéricas e de texto, essas ferramentas não vão reconhecer sua intenção e usarão como padrão o mapeamento descrito nas seguintes seções Mapeamento numérico e Mapeamento de texto e XML. Para obter mais informações sobre como gerar código com o arquivo DBML, confira Geração de código em LINQ to SQL.

O método DataContext.CreateDatabase cria uma coluna SQL do tipo numérico para mapear um tipo System.Enum CLR.

Mapeamento numérico

O LINQ to SQL permite mapear vários tipos numéricos CLR e SQL Server. A tabela a seguir mostra os tipos de CLR que o Designer Relacional de Objetos e o SQLMetal selecionam ao criar um modelo de objeto ou um arquivo de mapeamento externo com base no seu banco de dados.

Tipo do SQL Server Mapeamento do tipo CLR padrão usado pelo Designer Relacional de Objetos e pelo 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

A tabela a seguir mostra os mapeamentos de tipo padrão usados pelo método DataContext.CreateDatabase para definir o tipo de colunas SQL são criadas para mapear para tipos CLR definidos no seu modelo de objeto ou arquivos de mapeamento externo.

Tipo CLR Tipo padrão do SQL Server usado pelo 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

Há muitos outros mapeamentos numéricos que você pode escolher, mas alguns podem resultar em estouro ou exceções de perda de dados ao converter para ou do banco de dados. Para obter mais informações, confira Matriz de Comportamento em Tempo de Execução de Mapeamento de Tipo.

Tipos de decimal e dinheiro

A precisão padrão do tipo DECIMAL do SQL Server (18 dígitos decimais para a esquerda e para a direita do ponto decimal) é muito menor do que a precisão do tipo System.Decimal CLR ao qual está emparelhada por padrão. Isso pode levar na perda de precisão quando você salva dados no banco de dados. No entanto, apenas o oposto pode acontecer se o tipo DECIMAL do SQL Server é configurado com mais de 29 dígitos de precisão. Quando um tipo DECIMAL do SQL Server tiver sido configurado com uma precisão maior do que o System.Decimal CLR, a perda de precisão poderá ocorrer ao recuperar dados do banco de dados.

Os tipos MONEY e SMALLMONEY do SQL Server, que também são emparelhados com o tipo System.Decimal CLR por padrão, têm uma precisão muito menor, que pode resultar em estouro ou exceções de perda de dados ao salvar dados no banco de dados.

Mapeamento de texto e XML

Também há muitos tipos XML e baseados em texto que você pode mapear com o LINQ to SQL. A tabela a seguir mostra os tipos de CLR que o Designer Relacional de Objetos e o SQLMetal selecionam ao criar um modelo de objeto ou um arquivo de mapeamento externo com base no seu banco de dados.

Tipo do SQL Server Mapeamento do tipo CLR padrão usado pelo Designer Relacional de Objetos e pelo SQLMetal
CHAR System.String
NCHAR System.String
VARCHAR System.String
NVARCHAR System.String
TEXT System.String
NTEXT System.String
XML System.Xml.Linq.XElement

A tabela a seguir mostra os mapeamentos de tipo padrão usados pelo método DataContext.CreateDatabase para definir o tipo de colunas SQL são criadas para mapear para tipos CLR definidos no seu modelo de objeto ou arquivos de mapeamento externo.

Tipo CLR Tipo padrão do SQL Server usado pelo DataContext.CreateDatabase
System.Char NCHAR(1)
System.String NVARCHAR(4000)
System.Char[] NVARCHAR(4000)
Tipo personalizado implementando Parse() e ToString() NVARCHAR(MAX)

Há muitos outros mapeamentos XML e baseados em texto que você pode escolher, mas alguns podem resultar em estouro ou exceções de perda de dados ao converter para ou do banco de dados. Para obter mais informações, confira Matriz de Comportamento em Tempo de Execução de Mapeamento de Tipo.

Tipos XML

O tipo de dados XML do SQL Server está disponível a partir do Microsoft SQL Server 2005. Você pode mapear o tipo de dados XML do SQL Server para XElement, XDocument ou String. Se a coluna armazena os fragmentos XML que não podem ser lidos no XElement, a coluna deverá ser mapeada para String para evitar erros em tempo de execução. Os fragmentos XML que devem ser mapeados para String incluem o seguinte:

  • Uma sequência dos elementos XML

  • Atributos

  • Identificadores públicos (PI)

  • Comentários

Embora você possa mapear o XElement e o XDocument para o SQL Server conforme mostrado em Matriz de Comportamento em Tempo de Execução de Mapeamento de Tipo, o método DataContext.CreateDatabase não tem nenhum mapeamento padrão do tipo do SQL Server para esses tipos.

Tipos personalizados

Se uma classe implementa Parse() e ToString(), você pode mapear o objeto para qualquer tipo de texto SQL (CHAR, NCHAR, VARCHAR, NVARCHAR, TEXT, NTEXT, XML). O objeto é armazenado no banco de dados enviando o valor retornado por ToString() para a coluna mapeada do banco de dados. O objeto é reconstruído chamando Parse() na cadeia de caracteres retornada pelo banco de dados.

Observação

O LINQ to SQL não dá suporte à serialização usando System.Xml.Serialization.IXmlSerializable.

Mapeamento de data e hora

Com o LINQ to SQL, você pode mapear muito tipos de data e hora do SQL Server. A tabela a seguir mostra os tipos de CLR que o Designer Relacional de Objetos e o SQLMetal selecionam ao criar um modelo de objeto ou um arquivo de mapeamento externo com base no seu banco de dados.

Tipo do SQL Server Mapeamento do tipo CLR padrão usado pelo Designer Relacional de Objetos e pelo SQLMetal
SMALLDATETIME System.DateTime
DATETIME System.DateTime
DATETIME2 System.DateTime
DATETIMEOFFSET System.DateTimeOffset
DATE System.DateTime
TIME System.TimeSpan

A tabela a seguir mostra os mapeamentos de tipo padrão usados pelo método DataContext.CreateDatabase para definir o tipo de colunas SQL são criadas para mapear para tipos CLR definidos no seu modelo de objeto ou arquivos de mapeamento externo.

Tipo CLR Tipo padrão do SQL Server usado pelo DataContext.CreateDatabase
System.DateTime DATETIME
System.DateTimeOffset DATETIMEOFFSET
System.TimeSpan TIME

Há muitos outros mapeamentos de data e hora que você pode escolher, mas alguns podem resultar em estouro ou exceções de perda de dados ao converter para ou do banco de dados. Para obter mais informações, confira Matriz de Comportamento em Tempo de Execução de Mapeamento de Tipo.

Observação

Os tipos de dados DATETIME2, DATETIMEOFFSET, DATE e TIME do SQL Server estão disponíveis a partir do Microsoft SQL Server 2008. O LINQ to SQL oferece suporte ao mapeamento para esses novos tipos a partir do .NET Framework versão 3.5 SP1.

System.Datetime

O intervalo e a precisão do tipo System.DateTime CLR são maiores do que o intervalo e a precisão do tipo DATETIME do SQL Server, que é o mapeamento de tipo padrão para o método DataContext.CreateDatabase. Para ajudar a evitar exceções relacionadas a datas fora do intervalo de DATETIME, use DATETIME2, que está disponível a partir do Microsoft SQL Server 2008. DATETIME2 pode corresponder ao intervalo e à precisão do System.DateTime de CLR.

As datas do SQL Server não têm nenhum conceito de TimeZone, um recurso que tem suporte de modo avançado no CLR. Os valores TimeZone são salvos como estão no banco de dados sem conversão de TimeZone, independentemente das informações de DateTimeKind originais. Quando os valores DateTime são recuperados do banco de dados, eles são carregados como estão em um DateTime com um DateTimeKind de Unspecified. Para obter mais informações sobre os métodos System.DateTime com suporte, confira Métodos System.DateTime.

System.TimeSpan

O Microsoft SQL Server 2008 e o .NET Framework 3.5 SP1 permitem mapear o tipo System.TimeSpan CLR para o tipo TIME do SQL Server. No entanto, há uma grande diferença entre o intervalo ao qual o System.TimeSpan CLR dá suporte e a que o tipo TIME do SQL Server dá suporte. Os valores de mapeamento menores que 0 ou maiores que 23:59:59,9999999 horas para TIME do SQL resultará em exceções de estouro. Para obter mais informações, confira Métodos System.TimeSpan.

No Microsoft SQL Server 2000 e no SQL Server 2005, você não pode mapear campos de banco de dados para TimeSpan. No entanto, as operações no TimeSpan têm suporte porque os valores TimeSpan podem ser retornados da subtração de DateTime ou introduzidos em uma expressão como um literal ou uma variável associada.

Mapeamento binário

Há muitos tipos do SQL Server que podem mapear para o tipo System.Data.Linq.Binary CLR. A tabela a seguir mostra os tipos de SQL Server que fazem o Designer Relacional de Objetos e o SQLMetal definir um tipo System.Data.Linq.Binary CLR ao criar um modelo de objeto ou um arquivo de mapeamento externo com base no seu banco de dados.

Tipo do SQL Server Mapeamento do tipo CLR padrão usado pelo Designer Relacional de Objetos e pelo SQLMetal
BINARY(50) System.Data.Linq.Binary
VARBINARY(50) System.Data.Linq.Binary
VARBINARY(MAX) System.Data.Linq.Binary
VARBINARY(MAX) com o atributo FILESTREAM System.Data.Linq.Binary
IMAGE System.Data.Linq.Binary
TIMESTAMP System.Data.Linq.Binary

A tabela a seguir mostra os mapeamentos de tipo padrão usados pelo método DataContext.CreateDatabase para definir o tipo de colunas SQL são criadas para mapear para tipos CLR definidos no seu modelo de objeto ou arquivos de mapeamento externo.

Tipo CLR Tipo padrão do SQL Server usado pelo DataContext.CreateDatabase
System.Data.Linq.Binary VARBINARY(MAX)
System.Byte VARBINARY(MAX)
System.Runtime.Serialization.ISerializable VARBINARY(MAX)

Há muitos outros mapeamentos binários que você pode escolher, mas alguns podem resultar em estouro ou exceções de perda de dados ao converter para ou do banco de dados. Para obter mais informações, confira Matriz de Comportamento em Tempo de Execução de Mapeamento de Tipo.

SQL Server FILESTREAM

O atributo FILESTREAM para colunas VARBINARY(MAX) está disponível a partir do Microsoft SQL Server 2008; você pode mapeá-lo com o LINQ to SQL a partir do .NET Framework versão 3.5 SP1.

Embora você possa mapear colunas VARBINARY(MAX) com o atributo FILESTREAM para objetos Binary, o método DataContext.CreateDatabase não é capaz de criar automaticamente colunas com o atributo FILESTREAM. Para obter mais informações sobre FILESTREAM, confira FILESTREAM Overview.

Serialização binária

Se uma classe implementa a interface ISerializable, você poderá serializar um objeto para qualquer campo binário do SQL (BINARY, VARBINARY, IMAGE). O objeto é serializado e desserializado de acordo com a maneira como a interface ISerializable é implementada. Para obter mais informações, confira Serialização Binária.

Mapeamento variado

A tabela a seguir mostra os mapeamentos de tipo padrão para alguns tipos variados que ainda não foram mencionados. A tabela a seguir mostra os tipos de CLR que o Designer Relacional de Objetos e o SQLMetal selecionam ao criar um modelo de objeto ou um arquivo de mapeamento externo com base no seu banco de dados.

Tipo do SQL Server Mapeamento do tipo CLR padrão usado pelo Designer Relacional de Objetos e pelo SQLMetal
UNIQUEIDENTIFIER System.Guid
SQL_VARIANT System.Object

A tabela a seguir mostra os mapeamentos de tipo padrão usados pelo método DataContext.CreateDatabase para definir o tipo de colunas SQL são criadas para mapear para tipos CLR definidos no seu modelo de objeto ou arquivos de mapeamento externo.

Tipo CLR Tipo padrão do SQL Server usado pelo DataContext.CreateDatabase
System.Guid UNIQUEIDENTIFIER
System.Object SQL_VARIANT

O LINQ to SQL não dá suporte a nenhum outro mapeamentos de tipo para esses tipos variados. Para obter mais informações, confira Matriz de Comportamento em Tempo de Execução de Mapeamento de Tipo.

Confira também