DbArithmeticExpression-Argumente müssen einen gemeinsamen numerischen Typ haben

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

Dieser Linq-Ausdruck löst diese Ausnahme aus:

DbArithmeticExpression arguments must have a numeric common type.

Bitte helfen Sie!

Nawaz Dhandala
quelle
Was ist das Ergebnis von clientDateTime - o.ClientDateTimeStamp?
Shahkalpesh
Normalerweise sollte dies ein Objekt von TimeSpan sein, in EF wird eine Ausnahme ausgelöst.
Nawaz Dhandala

Antworten:

247

Arithmetik mit DateTimewird in Entity Framework 6 und früheren Versionen nicht unterstützt. Sie müssen DbFunctions * verwenden. Für den ersten Teil Ihrer Aussage also etwas wie:

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

Beachten Sie, dass die DiffHoursMethode akzeptiert Nullable<DateTime>.

Der Entity Framwork-Kern (bei Verwendung mit SQL Server, möglicherweise anderen Datenbankanbietern) unterstützt die DateTime- AddXxxFunktionen (wie z AddHours. B. ). Sie werden DATEADDin SQL übersetzt.

* EntityFunctionsvor Entity Framework Version 6.

Gert Arnold
quelle
2

Ich weiß, dass dies eine alte Frage ist, aber in Ihrem speziellen Fall, anstatt DBFunctionswie von @GertArnold vorgeschlagen zu verwenden, können Sie die Operation nicht einfach umkehren und die betreffende Arithmetik aus dem Lambda entfernen?

Immerhin clientDateTimeund time24sind feste Werte, so dass ihre Differenz nicht bei jeder Iteration neu berechnet werden muss.

Mögen:

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

Dieser Refactor ist normalerweise möglich, wenn Sie versuchen, die gespeicherte Datumszeit, die um einen festen Zeitstempel verschoben wurde, mit einer anderen Datumszeit zu vergleichen.

SoonDead
quelle
Ich hatte genau diese Situation und das half. Der Umfang dieser Lösung ist jedoch sehr auf eine bestimmte Art von Problem beschränkt.
Zimano
@Zimano Es löst das OP-Problem, ohne dass er Technologien ändern oder auf Hacks zurückgreifen muss. Wenn es so umgestaltet werden kann, dann mach es, wenn nicht, dann mach es wie in der akzeptierten Antwort.
SoonDead
1

Wenn die Leistung nicht das eigentliche Ziel ist, können Sie es auch versuchen AsEnumerable(). So wäre es wie

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

Durch Hinzufügen von AsEnumerable () wird die SQL-Abfrage in eine Entität konvertiert und es können .NET-Funktionen auf diesen ausgeführt werden. Weitere Informationen zu AsEnumerable finden Sie hier

vermasselt
quelle