2010-11-10 30 views
85

En mi aplicación utilizo Entity Framework.Linq to EntityFramework DateTime

Mi Tabla

-Article 
-period 
-startDate 

que necesitan los registros que coinciden =>DateTime.Now > startDate and (startDate + period) > DateTime.Now

probé este código, pero su ahora trabaja

Context.Article 
    .Where(p => p.StartDate < DateTime.Now) 
    .Where(p => p.StartDate.AddDays(p.Period) > DateTime.Now) 

Cuando ejecuto mi código de la siguiente excepción se produce

LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.

+0

¿Qué tipo es 'period'? 'AddDays' es la función incorrecta si es un' doble'. –

+0

tipos de períodos es int – Yucel

Respuesta

160

Al utilizar LINQ para Entity Framework, sus predicados dentro de la cláusula Where se traducen a SQL. Está obteniendo ese error porque no hay traducción a SQL para DateTime.Add() que tenga sentido.

Una solución alternativa rápida sería leer los resultados de la primera instrucción WHERE en la memoria y luego usar LINQ to Objects para terminar filtrado:

Context.Article.Where(p => p.StartDate < DateTime.Now) 
       .ToList() 
       .Where(p => p.StartDate.AddDays(p.Period) > DateTime.Now); 

También puede probar el método EntityFunctions.AddDays si estás utilizando .NET 4.0:

Context.Article.Where(p => p.StartDate < DateTime.Now) 
       .Where(p => EntityFunctions.AddDays(p.StartDate, p.Period) 
        > DateTime.Now); 

Nota: En EF 6 ahora es System.Data.Entity.DbFunctions.AddDays.

+32

Esto es un trabajo peligroso, ¿qué sucede si ToList() devuelve una gran cantidad de datos? –

+0

@Stefan P. - Entonces la primera declaración leería una gran cantidad de datos en la memoria. El segundo método debería estar bien, pero solo está disponible con .NET 4.0. –

+6

Gracias por el consejo de EntityFunctions.AddDays Estoy usando EF .net 4.0 pero no sabía sobre EntityFunctions, lo investigaré. –

3

¿Qué hay de restar 2 días a partir de DateTime.Now:

Context.Article 
.Where(p => p.StartDate < DateTime.Now) 
.Where(p => p.StartDate > DateTime.Now.Subtract(new TimeSpan(2, 0, 0, 0))) 

Para ser honesto, no está seguro de lo que está tratando de lograr, pero esto puede funcionar

+0

Los artículos comenzarán a mostrarse en StartDate y finalizarán después de x (período) días. Esto es lo que estoy tratando de hacer. La segunda solución de Justin Niessner funcionó muy bien para lo que quiero ver – Yucel

+1

¡Obtuve el mismo error al usar Restar! –

71

Creo que esto es lo que el pasado respuesta estaba tratando de sugerir, pero en lugar de tratar de añadir días a p.startdat (algo que no se puede convertir en una instrucción SQL) por qué no hacer algo que puede ser equiparada a SQL:

var baselineDate = DateTime.Now.AddHours(-24); 

something.Where(p => p.startdate >= baselineDate) 
+7

Esta es una respuesta mucho mejor que la respuesta aceptada con más votos. Es más simple, más seguro y más eficiente. –

+1

@Adrian Carr: puede ser mejor para este caso de uso pero no para tantos como la solución 'EntityFunctions'. Aquí, el segundo operando no se recupera de otra entidad en la consulta y se puede calcular antes de consultar. Si ambos operandos se encontraran en db, la solución 'EntityFunctions' aún sería adecuada, mientras que la solución de esta respuesta ya no funcionaría. –

1

Si necesita que su expresión se traduzca a SQL, puede intentar usar

System.Data.Entity.Core.Objects.AddDays method.

En realidad, está marcado como obsoleto, pero funciona. Debería ser reemplazado por System.Data.Entity.DbFunctions.AddDays pero no puedo encontrarlo ...

+0

¡Esto no agrega nada más que la respuesta aceptada de 4 años antes! –

+0

@AndrewHarris también mi respuesta es hace 4 años respuesta. En la primera versión de la respuesta había una ToList (=> materialización de datos) antes de Where (ver el primer comentario de la respuesta). – bubi