124 votes

Les arguments de DbArithmeticExpression doivent avoir un type commun numérique.

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(); 

Cette expression Linq génère cette exception :

DbArithmeticExpression arguments must have a numeric common type.

Aidez-nous !

0 votes

Quels sont les résultats de clientDateTime - o.ClientDateTimeStamp ?

0 votes

Mais ce n'est pas un objet de type TimeSpan qui doit être utilisé, car une exception est levée dans EF.

258voto

Gert Arnold Points 27642

Arithmétique avec DateTime n'est pas pris en charge dans Entity Framework 6 et les versions antérieures. Vous devez utiliser DbFunctions *. Donc, pour la première partie de votre déclaration, quelque chose comme :

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

Notez que le DiffHours La méthode accepte Nullable<DateTime> .

Entité Framwork core (lorsqu'il est utilisé avec Sql Server, voire d'autres fournisseurs de données) prend en charge l'option DateTime. AddXxx (comme AddHours ). Ils sont traduits en DATEADD en SQL.

* <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.entityfunctions.aspx" rel="noreferrer"><code>EntityFunctions</code></a> avant la version 6 d'Entity Framework.

10voto

edicius6 Points 81

Et pour EF v6.0+, ils ont déplacé cette fonctionnalité vers System.Data.Entity.DbFunctions.DiffHours .

2voto

SoonDead Points 3009

Je sais que c'est une vieille question mais dans votre cas spécifique, au lieu d'utiliser DBFunctions comme suggéré par @GertArnold , ne pourriez-vous pas simplement inverser l'opération en déplaçant l'arithmétique en question de la Lambda ?

Après tout clientDateTime et time24 sont des valeurs fixes, leur différence n'a donc pas besoin d'être recalculée à chaque itération.

Comme :

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();

Ce remaniement est généralement possible si vous essayez de comparer la date stockée décalée par un horodatage fixe avec une autre date.

0 votes

J'ai eu exactement la même situation, et ça m'a aidé. Cependant, la portée de cette solution est très limitée à un type de problème spécifique.

0 votes

@Zimano Il résout le problème du PO sans l'obliger à changer de technologie ou à recourir à des hacks. Si cela peut être refactorisé de cette façon, alors faites-le, sinon, faites-le comme dans la réponse acceptée.

1voto

messed-up Points 357

Dans l'autre sens, si la performance n'est pas le véritable objectif, vous pouvez essayer d'utiliser AsEnumerable() . Donc, ce serait comme

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

L'ajout de AsEnumerable() convertira la requête SQL en entité et permettra d'exécuter des fonctions .Net sur celles-ci. Pour plus d'informations, voir ici à propos de AsEnumerable

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X