EF DateTime2 y el índice perdido

the bug hunting!

Hoy me han remitido un caso muy curioso de EF y el tratamiento de los campos DateTime. Básicamente, lo que me comentaban era que EF generaba una consulta incorrecta incluyendo un CAST a DateTime2, con lo cual hacía imposible la utilización del índice que la base de datos tenía sobre esta columna. Para seros sinceros, me sonó raro, puesto que es habitual ver el profiling de las consultas y me hubiera cantado a la primera, por lo que me puse a investigar el tema. Como siempre, lo primero es una aplicación de mínimos y por ello, nada más tonto que lo siguiente:

 


 

Ahora, solamente nos queda tirar una consulta y ver que se está ejecutando:

 


 


 

Bien, perfecto.. No veo el problema que se comenta!!!!!!!!!  Revisando el código en el que aparecía este problema, buscando cualquier nota diferente como que estuviera forzando el tipo a DateTime2 etc.. nos dimos cuenta que la única diferencia era que en su ejemplo los campos eran Nullables. Por lo tanto, probamos a cambiar el ejemplo tonto anterior haciendo uso de DateTime?.

 


Revisando la consulta con el profiler nos dimos cuenta de que efectivamente, si hacemos uso de DateTime? las consultas generan un CAST incorrecto que tira por tierra nuestros índices…


 

Por supuesto esto es un bug, un bug que esperemos que arreglen en la siguiente versión, mientras tanto, ya sabéis, cuidado con los DateTime?.

P.d: Vizoso, gracias por reportar el bug!!

 

Saludos

Unai

5 comentarios en “EF DateTime2 y el índice perdido”

  1. Hola Unai,

    La verdad que me has quitado parte de mi último capítulo de la “historia interminable” :). Pero bueno daremos una vuelta de tuerca a ver que pasa con otras situaciones de Null o por lo menos citamos el Warning de compilación:).

    De todas formas aunque es un bug como comentas poco sentido tiene hacer mayor y menor que Null excepto que no encuentres nada y más si el campo no permite Null.

    Saludos.

  2. Bueno, es un bug porque estan haciendo algo en base a un tipo y no en la informacion del store.Si tiene mas o menos sentido en este caso no me importa mucho, se podria reproducir con escenarioa que si que lo tengan.
    Unai

  3. Hola,

    Efectivamente que en este escenario no importa mucho y en otros puede importar y de lo lindo e incluso en este si el volumen de registros es grande, pero sentido creo que tiene menos y me explico.

    Si tienes grabado un DateTime en tu store o bb.dd que no permite null que pintan dos variables DateTime definidas como Nullable y preguntar por mayor y menor. En todo caso si fuese por igual algún sentido le vería a esa DateTime?.

    Saludos.

  4. Hola, si declaras
    public DateTime Fecha { get; set; }

    Se crea como:
    [Fecha] [datetime] NOT NULL

    Hasta aquí, es el ejemplo anterior.

    Pero si declaras
    public DateTime? Fecha { get; set; }

    Se crea como:
    [Fecha] [datetime],

    Y el resultado de la query sería:
    exec sp_executesql N’SELECT
    [Extent1].[Id] AS [Id],
    [Extent1].[Fecha] AS [Fecha]
    FROM [dbo].[Samples] AS [Extent1]
    WHERE (@p__linq__0 < [Extent1].[Fecha]) AND ([Extent1].[Fecha] < @p__linq__1)',N'@p__linq__0 datetime2(7),@p__linq__1 datetime2(7)',@p__linq__0='2012-03-26 21:02:51.4361089',@p__linq__1='2012-03-28 21:02:51.4361089' Por lo que, al mapear el tipo de CLR a un tipo de SQL Server, la única diferenca entre un DateTime y un DateTime? es que sea nullable o no, pero parece que si todos son nullables, no se ve en la necesidad de hacer ese CAST o no se produce el fallo. También probando a especificar el tipo a mano con un: public class SampleEntityConfiguration : EntityTypeConfiguration
    {
    public SampleEntityConfiguration()
    {
    this.Property(l => l.Fecha)
    .HasColumnType(“datetime2”);
    }
    }

    Crea el campo como:
    [Fecha] [datetime2](7) NOT NULL,

    Pero sigue haciendo:

    exec sp_executesql N’SELECT
    [Extent1].[Id] AS [Id],
    [Extent1].[Fecha] AS [Fecha]
    FROM [dbo].[Samples] AS [Extent1]
    WHERE (@p__linq__0 < CAST( [Extent1].[Fecha] AS datetime2)) AND ( CAST( [Extent1].[Fecha] AS datetime2) < @p__linq__1)',N'@p__linq__0 datetime2(7),@p__linq__1 datetime2(7)',@p__linq__0='2012-03-26 21:15:22.1000444',@p__linq__1='2012-03-28 21:15:22.1000444' El comportamiento sigue siendo curioso. Huelga decir que tener nullable sobre Fecha si va a ser índice de la tabla no tiene mucho sentido, pero Unai tiene razón, esto puede saltar en cualquier parte. Saludos!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *