Compartir a través de


Asignación de tipos entre CLR y SQL

En LINQ to SQL, el modelo de datos de una base de datos relacional se asigna a un modelo de objetos expresado en el lenguaje de programación que prefiera. Cuando la aplicación se ejecuta, LINQ to SQL convierte las consultas integradas del lenguaje del modelo de objetos a SQL y las envía a la base de datos para su ejecución. Cuando la base de datos devuelve los resultados, LINQ to SQL los vuelve a convertir en objetos con los que pueda trabajar en su propio lenguaje de programación.

Para convertir los datos entre el modelo de objetos y la base de datos, se debe definir una asignación de tipos. LINQ to SQL utiliza una asignación de tipos para que cada tipo de Common Language Runtime (CLR) se corresponda con un tipo de SQL Server concreto. Las asignaciones de tipos y otra información de asignación, como las relaciones de tablas y estructuras de bases de datos, se pueden definir en el modelo de objetos con una asignación basada en atributos. Opcionalmente, la información de asignación se puede especificar fuera del modelo de objetos con un archivo de asignación externo. Para más información, consulte Asignación basada en atributos y Asignación externa.

En este tema se tratan los puntos siguientes:

Asignación de tipos predeterminados

Puede crear automáticamente el modelo de objetos o el archivo de asignación con Object Relational Designer o la herramienta de línea de comandos SQLMetal. Las asignaciones de tipos predeterminadas de estas herramientas definen qué tipos de CLR se deben elegir para asignarlos a columnas en la base de datos SQL Server. Para más información sobre el uso de estas herramientas, consulte Crear el modelo de objetos.

También puede utilizar el método CreateDatabase para crear una base de datos de SQL Server según la información de asignación del modelo de objetos o del archivo de asignación externo. Las asignaciones de tipos predeterminadas del método CreateDatabase definen qué tipo de columnas de SQL Server se deben crear para asignarlas a los tipos de CLR en el modelo de objetos. Para más información, consulte Cómo crear dinámicamente una base de datos.

Matriz de comportamiento de la asignación de tipos en tiempo de ejecución

En el diagrama siguiente se muestra el comportamiento de las asignaciones de tipos específicos que se espera en tiempo de ejecución, cuando los datos se recuperan de la base de datos o se guardan en ella. Con la excepción de la serialización, LINQ to SQL no admite la asignación entre los tipos de datos de CLR o SQL Server no especificados en esta matriz. Para más información sobre la compatibilidad con la serialización, consulte Serialización binaria.

SQL Server to SQL CLR data type mapping table

Nota:

Algunas asignaciones de tipos pueden tener como resultado excepciones de desbordamiento o de pérdida de datos mientras se convierten a la base de datos o desde ella.

Asignación de tipos personalizados

Con LINQ to SQL, no está limitado a usar las asignaciones de tipos predeterminadas de Object Relational Designer, SQLMetal y el método CreateDatabase. Puede crear asignaciones de tipos personalizadas especificándolas explícitamente en un archivo DBML. Después, puede usar ese archivo para crear el código del modelo de objetos y el archivo de asignación. Para más información, consulte Asignaciones de tipos personalizadas entre SQL y CLR.

Diferencias de comportamiento entre la ejecución de CLR y SQL

Debido a las diferencias entre CLR y SQL Server en cuanto a la precisión y la ejecución, puede recibir diferentes resultados o experimentar un comportamiento distinto en función de dónde se realicen los cálculos. Los cálculos realizados en las consultas LINQ to SQL se traducen, de hecho, a Transact-SQL y después se ejecutan en la base de datos de SQL Server. Los cálculos realizados fuera de las consultas LINQ to SQL se ejecutan en el contexto de CLR.

Por ejemplo, a continuación se indican algunas diferencias de comportamiento entre CLR y SQL Server:

  • SQL Server ordena ciertos tipos de datos de forma diferente a los datos del tipo equivalente en CLR. Por ejemplo, los datos de SQL Server del tipo UNIQUEIDENTIFIER se ordenan de forma diferente a los datos de CLR del tipo System.Guid.

  • SQL Server trata ciertas operaciones de comparación de cadenas de forma diferente a CLR. En SQL Server, el comportamiento de comparación de cadenas depende de la configuración de intercalación del servidor. Para más información, consulte Trabajar con intercalaciones.

  • SQL Server puede devolver valores diferentes a los que devuelve CLR para algunas funciones asignadas. Por ejemplo, las funciones de igualdad tendrán resultados distintos porque SQL Server considera que dos cadenas son iguales si solo se diferencian en el espacio en blanco final, mientras que CLR considera que no son iguales.

Asignación de enumeración

LINQ to SQL admite la asignación del tipo System.Enum de CLR a tipos de SQL Server de dos maneras:

  • Asignación a tipos SQL numéricos (TINYINT, SMALLINT, INT, BIGINT)

    Al asignar un tipo System.Enum de CLR a un tipo numérico de SQL, el valor entero subyacente del tipo System.Enum de CLR se asigna al valor de la columna de base de datos de SQL Server. Por ejemplo, si un elemento System.Enum denominado DaysOfWeek contiene un miembro denominado Tue con un valor entero subyacente de 3, ese miembro se asigna a un valor de base de datos de 3.

  • Asignación a tipos SQL de texto (CHAR, NCHAR, VARCHAR, NVARCHAR)

    Al asignar un tipo System.Enum de CLR a un tipo de texto de SQL, el valor de la base de datos SQL se asigna a los nombres de los miembros System.Enum de CLR. Por ejemplo, si un tipo System.Enum denominado DaysOfWeek contiene un miembro denominado Tue con un valor entero subyacente de 3, ese miembro se asigna a un valor de base de datos de Tue.

Nota:

Cuando los tipos de texto de SQL se asignan a System.Enum de CLR, solo se incluyen los nombres de los miembros Enum en la columna de SQL asignada. No se admiten otros valores en la columna de SQL asignada a Enum.

Object Relational Designer y la herramienta de línea de comandos SQLMetal no pueden asignar automáticamente un tipo SQL a una clase Enum de CLR. Debe configurar explícitamente esta asignación personalizando un archivo DBML para que lo usen Object Relational Designer y SQLMetal. Para más información acerca de la asignación de tipos personalizados, consulte Asignaciones de tipos personalizadas entre SQL y CLR.

Puesto que una columna SQL de enumeración tendrá el mismo tipo que el resto de las columnas numéricas y de texto, estas herramientas no reconocerán el intento y la asignación se realizará de forma predeterminada tal y como se describe en las siguientes secciones Asignación numérica y Asignación de texto y XML. Para más información sobre el código generador con el archivo DBML, consulte Generación de código en LINQ to SQL.

El método DataContext.CreateDatabase crea una columna de SQL de tipo numérico para asignar un tipo System.Enum de CLR.

Asignación numérica

LINQ to SQL permite asignar muchos tipos numéricos de CLR y SQL Server. En la tabla siguiente se muestran los tipos de CLR que Object Relational Designer y SQLMetal seleccionan al crear un modelo de objetos o un archivo de asignación externo de acuerdo con la base de datos.

Tipo de datos de SQL Server Asignación de tipos de CLR predeterminada usada por Object Relational Designer y 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

En la tabla siguiente se muestran las asignaciones de tipos predeterminadas que el método DataContext.CreateDatabase utiliza para definir qué tipo de columnas de SQL se deben crear para asignarlas a los tipos de CLR definidos en el modelo de objetos o en el archivo de asignación externo.

Tipo CLR Tipo predeterminado de SQL Server utilizado por 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

Hay muchas otras asignaciones de tipos numéricos entre las que puede elegir, pero algunas pueden tener como resultado excepciones de desbordamiento o de pérdida de datos mientras se trasladan a la base de datos o desde ella. Para más información, consulte Matriz de comportamiento de la asignación de tipos en tiempo de ejecución.

Tipos Decimal y Money

La precisión predeterminada del tipo DECIMAL de SQL Server (18 dígitos decimales a la derecha y a la izquierda del separador decimal) es menor que la precisión del tipo de CLR System.Decimal con el que se empareja de forma predeterminada. Esto puede producir una pérdida de precisión cuando los datos se guardan en la base de datos. Sin embargo, puede ocurrir exactamente lo contrario si el tipo DECIMAL de SQL Server se configura con más de 29 dígitos de precisión. Cuando se ha configurado un tipo DECIMAL de SQL Server con mayor precisión que el tipo System.Decimal de CLR, la pérdida de precisión se produce al recuperar los datos de la base de datos.

Los tipos MONEY y SMALLMONEY de SQL Server, que también están emparejados con el tipo System.Decimal de CLR de forma predeterminada, tienen mucha menos precisión, por lo que pueden producirse excepciones de desbordamiento o de pérdida de datos al guardar los datos en la base de datos.

Asignación de texto y XML

También hay muchos tipos XML y basados en texto que se pueden asignar con LINQ to SQL. En la tabla siguiente se muestran los tipos de CLR que Object Relational Designer y SQLMetal seleccionan al crear un modelo de objetos o un archivo de asignación externo de acuerdo con la base de datos.

Tipo de datos de SQL Server Asignación de tipos de CLR predeterminada usada por Object Relational Designer y SQLMetal
CHAR System.String
NCHAR System.String
VARCHAR System.String
NVARCHAR System.String
TEXT System.String
NTEXT System.String
XML System.Xml.Linq.XElement

En la tabla siguiente se muestran las asignaciones de tipos predeterminadas que el método DataContext.CreateDatabase utiliza para definir qué tipo de columnas de SQL se deben crear para asignarlas a los tipos de CLR definidos en el modelo de objetos o en el archivo de asignación externo.

Tipo CLR Tipo predeterminado de SQL Server utilizado por DataContext.CreateDatabase
System.Char NCHAR(1)
System.String NVARCHAR(4000)
System.Char[] NVARCHAR(4000)
Tipo personalizado que implementa Parse() y ToString() NVARCHAR(MAX)

Hay muchas otras asignaciones de XML y basadas en texto entre las que puede elegir, pero algunas pueden tener como resultado excepciones de desbordamiento o de pérdida de datos mientras se trasladan a o desde la base de datos. Para más información, consulte Matriz de comportamiento de la asignación de tipos en tiempo de ejecución.

Tipos XML

El tipo de datos XML de SQL Server está disponible a partir de Microsoft SQL Server 2005. Puede asignar el tipo de datos XML de SQL Server a XElement, XDocument o String. Si la columna almacena fragmentos XML que no se pueden leer en XElement, dicha columna debe asignarse a String para evitar errores en tiempo de ejecución. Entre los fragmentos XML que se deben asignar a String se incluyen los siguientes:

  • Una secuencia de elementos XML

  • Atributos

  • Identificadores públicos (PI)

  • Comentarios

Aunque puede asignar XElement y XDocument a SQL Server como se muestra en Matriz de comportamiento de la asignación de tipos en tiempo de ejecución, el método DataContext.CreateDatabase no dispone de ninguna asignación predeterminada de tipos de SQL Server para estos tipos.

Tipos personalizados

Si una clase implementa Parse() y ToString(), el objeto se puede asignar a cualquier tipo de texto de SQL (CHAR, NCHAR, VARCHAR, NVARCHAR, TEXT, NTEXT, XML). El objeto se almacena en la base de datos enviando el valor devuelto por ToString() a la columna de base de datos asignada. El objeto se reconstruye invocando a Parse() en la cadena devuelta por la base de datos.

Nota

LINQ to SQL no admite la serialización mediante System.Xml.Serialization.IXmlSerializable.

Asignación de fecha y hora

Con LINQ to SQL, se pueden asignar muchos tipos de fecha y hora de SQL Server. En la tabla siguiente se muestran los tipos de CLR que Object Relational Designer y SQLMetal seleccionan al crear un modelo de objetos o un archivo de asignación externo de acuerdo con la base de datos.

Tipo de datos de SQL Server Asignación de tipos de CLR predeterminada usada por Object Relational Designer y SQLMetal
SMALLDATETIME System.DateTime
DATETIME System.DateTime
DATETIME2 System.DateTime
DATETIMEOFFSET System.DateTimeOffset
DATE System.DateTime
TIME System.TimeSpan

En la tabla siguiente se muestran las asignaciones de tipos predeterminadas que el método DataContext.CreateDatabase utiliza para definir qué tipo de columnas de SQL se deben crear para asignarlas a los tipos de CLR definidos en el modelo de objetos o en el archivo de asignación externo.

Tipo CLR Tipo predeterminado de SQL Server utilizado por DataContext.CreateDatabase
System.DateTime DATETIME
System.DateTimeOffset DATETIMEOFFSET
System.TimeSpan TIME

Hay muchas otras asignaciones de fecha y hora entre las que puede elegir, pero algunas pueden tener como resultado excepciones de desbordamiento o de pérdida de datos mientras se trasladan a o desde la base de datos. Para más información, consulte Matriz de comportamiento de la asignación de tipos en tiempo de ejecución.

Nota

Los tipos de SQL Server DATETIME2, DATETIMEOFFSET, DATE y TIME están disponibles a partir de Microsoft SQL Server 2008. LINQ to SQL admite la asignación a estos tipos nuevos a partir del Service Pack 1 de .NET Framework 3.5.

System.Datetime

El intervalo y la precisión del tipo System.DateTime de CLR son mayores que el intervalo y la precisión del tipo DATETIME de SQL Server, que es la asignación de tipos predeterminada para el método DataContext.CreateDatabase. Para evitar las excepciones relacionadas con los datos que están fuera del intervalo de DATETIME, utilice DATETIME2, que está disponible a partir de Microsoft SQL Server 2008. DATETIME2 puede alcanzar la precisión y el intervalo del tipo de CLR System.DateTime.

Las fechas de SQL Server no disponen del concepto de TimeZone, que es una característica totalmente admitida en CLR. Los valores de TimeZone se guardan tal como están en la base de datos sin conversión de TimeZone, independientemente de la información de DateTimeKind original. Cuando los valores DateTime se recuperan de la base de datos, su valor se carga tal cual en DateTime, con un valor DateTimeKind de Unspecified. Para más información acerca de los métodos System.DateTime admitidos, consulte Métodos System.DateTime.

System.TimeSpan

Microsoft SQL Server 2008 y .NET Framework 3.5 SP1 permiten asignar el tipo System.TimeSpan de CLR al tipo TIME de SQL Server. Sin embargo, existe una gran diferencia entre el intervalo que admite el tipo System.TimeSpan de CLR y el que admite el tipo TIME de SQL Server. La asignación de valores menores que 0 horas o mayores que 23:59:59.9999999 horas al tipo TIME de SQL producirá excepciones de desbordamiento. Para más información, consulte Métodos System.TimeSpan.

En Microsoft SQL Server 2000 y SQL Server 2005, no se pueden asignar campos de base de datos a TimeSpan. Sin embargo, se admiten las operaciones en TimeSpan porque se pueden devolver valores TimeSpan a partir de la sustracción de DateTime o se pueden incluir en una expresión como una variable literal o una variable enlazada.

Asignación binaria

Hay muchos tipos de SQL Server que se pueden asignar al tipo System.Data.Linq.Binary de CLR. En la tabla siguiente se muestran los tipos de SQL Server que provocan que Object Relational Designer y SQLMetal definan un tipo System.Data.Linq.Binary de CLR al crear un modelo de objetos o un archivo de asignación externo de acuerdo con la base de datos.

Tipo de datos de SQL Server Asignación de tipos de CLR predeterminada usada por Object Relational Designer y SQLMetal
BINARY(50) System.Data.Linq.Binary
VARBINARY(50) System.Data.Linq.Binary
VARBINARY(MAX) System.Data.Linq.Binary
VARBINARY(MAX) con el atributo FILESTREAM System.Data.Linq.Binary
IMAGE System.Data.Linq.Binary
TIMESTAMP System.Data.Linq.Binary

En la tabla siguiente se muestran las asignaciones de tipos predeterminadas que el método DataContext.CreateDatabase utiliza para definir qué tipo de columnas de SQL se deben crear para asignarlas a los tipos de CLR definidos en el modelo de objetos o en el archivo de asignación externo.

Tipo CLR Tipo predeterminado de SQL Server utilizado por DataContext.CreateDatabase
System.Data.Linq.Binary VARBINARY(MAX)
System.Byte VARBINARY(MAX)
System.Runtime.Serialization.ISerializable VARBINARY(MAX)

Hay muchas otras asignaciones binarias entre las que puede elegir, pero algunas pueden tener como resultado excepciones de desbordamiento o de pérdida de datos mientras se trasladan a o desde la base de datos. Para más información, consulte Matriz de comportamiento de la asignación de tipos en tiempo de ejecución.

SQL Server FILESTREAM

El atributo FILESTREAM para las columnas VARBINARY(MAX) está disponible a partir de Microsoft SQL Server 2008; se le pueden asignar elementos con LINQ to SQL a partir del Service Pack 1 de .NET Framework 3.5.

Aunque puede asignar columnas VARBINARY(MAX) con el atributo FILESTREAM a objetos Binary, el método DataContext.CreateDatabase no puede crear columnas automáticamente con el atributo FILESTREAM. Para más información sobre FILESTREAM, consulte Información general de FILESTREAM.

Serialización binaria

Si una clase implementa la interfaz ISerializable, se puede serializar un objeto en cualquier campo binario de SQL (BINARY, VARBINARY, IMAGE). El objeto se serializa o deserializa de acuerdo con la forma en que se haya implementado la interfaz ISerializable. Para más información, consulte Serialización binaria.

Asignaciones varias

En la tabla siguiente se muestran las asignaciones de tipos predeterminadas para varios tipos que aún no se han mencionado. En la tabla siguiente se muestran los tipos de CLR que Object Relational Designer y SQLMetal seleccionan al crear un modelo de objetos o un archivo de asignación externo de acuerdo con la base de datos.

Tipo de datos de SQL Server Asignación de tipos de CLR predeterminada usada por Object Relational Designer y SQLMetal
UNIQUEIDENTIFIER System.Guid
SQL_VARIANT System.Object

En la tabla siguiente se muestran las asignaciones de tipos predeterminadas que el método DataContext.CreateDatabase utiliza para definir qué tipo de columnas de SQL se deben crear para asignarlas a los tipos de CLR definidos en el modelo de objetos o en el archivo de asignación externo.

Tipo CLR Tipo predeterminado de SQL Server utilizado por DataContext.CreateDatabase
System.Guid UNIQUEIDENTIFIER
System.Object SQL_VARIANT

LINQ to SQL no admite ninguna otra asignación de tipos para estos tipos varios. Para más información, consulte Matriz de comportamiento de la asignación de tipos en tiempo de ejecución.

Consulte también