Los argumentos DbArithmeticExpression deben tener un tipo común numérico

120
TimeSpan time24 = new TimeSpan(24, 0, 0);
TimeSpan time18 = new TimeSpan(18, 0, 0);    

// first get today's sleeping hours
List<Model.Sleep> sleeps = context.Sleeps.Where(
    o => (clientDateTime - o.ClientDateTimeStamp < time24) && 
          o.ClientDateTimeStamp.TimeOfDay > time18 && 
          clientDateTime.TimeOfDay < time18 && 
          o.UserID == userid).ToList(); 

Esta expresión de Linq arroja esta excepción:

DbArithmeticExpression arguments must have a numeric common type.

¡Por favor ayuda!

Nawaz Dhandala
fuente
¿Cuáles son los resultados clientDateTime - o.ClientDateTimeStamp?
Shahkalpesh
Normalmente, eso debería ser un objeto de TimeSpan, en EF se lanza una excepción.
Nawaz Dhandala

Respuestas:

247

La aritmética con DateTimeno es compatible con Entity Framework 6 y versiones anteriores. Tienes que usar DbFunctions *. Entonces, para la primera parte de su declaración, algo como:

var sleeps = context.Sleeps(o =>
    DbFunctions.DiffHours(o.ClientDateTimeStamp, clientDateTime) < 24);

Tenga en cuenta que el DiffHours método acepta Nullable<DateTime>.

Entity Framwork core (cuando se usa con Sql Server, tal vez otros proveedores de base de datos) admite las AddXxxfunciones DateTime (comoAddHours ). Están traducidos a DATEADDSQL.

* EntityFunctionsantes de Entity Framework versión 6.

Gert Arnold
fuente
2

Sé que esta es una pregunta antigua, pero en su caso específico en lugar de usar DBFunctions como sugiere @GertArnold, ¿no podría simplemente invertir la operación y sacar la aritmética en cuestión del Lambda?

Después de todo, clientDateTimey time24son valores fijos, por lo que su diferencia no necesita recalcularse en cada iteración.

Me gusta:

TimeSpan time24 = new TimeSpan(24, 0, 0);
TimeSpan time18 = new TimeSpan(18, 0, 0);    

var clientdtminus24 = clientDateTime - time24;

// first get today's sleeping hours
List<Model.Sleep> sleeps = context.Sleeps.Where(
    o => (clientdtminus24 < o.ClientDateTimeStamp) && 
          o.ClientDateTimeStamp.TimeOfDay > time18 && 
          clientDateTime.TimeOfDay < time18 && 
          o.UserID == userid).ToList();

Esta refactorización suele ser posible si intenta comparar la fecha y hora almacenada desplazada por una marca de tiempo fija con otra fecha y hora.

Pronto Muerto
fuente
Tenía esta situación exacta, y esto ayudó. Sin embargo, el alcance de esta solución está muy limitado a un tipo específico de problema.
Zimano
@Zimano Soluciona el problema de los OP sin necesidad de que cambie de tecnología o recurra a hacks. Si se puede refactorizar así, hágalo, si no, hágalo como en la respuesta aceptada.
SoonDead
1

Por otro lado, si el rendimiento no es el verdadero objetivo, puede intentar usar AsEnumerable(). Entonces, sería como

List<Model.Sleep> sleeps = context.Sleeps.AsEnumerable().Where(....

Agregar AsEnumerable () convertirá la consulta SQL en entidad y permitirá ejecutar funciones .Net en ellos. Para obtener más información, consulte aquí acerca de AsEnumerable

hecho un desastre
fuente