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

This Linq expression throws this exception:

DbArithmeticExpression arguments must have a numeric common type.

Please Help!

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
Nawaz Dhandala
  • 2,046
  • 2
  • 17
  • 23

3 Answers3

276

Arithmetic with DateTime is not supported in Entity Framework 6 and earlier. You have to use DbFunctions*. So, for the first part of your statement, something like:

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

Note that the DiffHours method accepts Nullable<DateTime>.

Entity Framwork core (when used with Sql Server, maybe other db providers) supports the DateTime AddXxx functions (like AddHours). They're translated into DATEADD in SQL.

*EntityFunctions prior to Entity Framework version 6.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
2

I know that this is an old question but in your specific case instead of using DBFunctions as suggested by @GertArnold , couldn't you just invert the operation move out the arithmetic in question from the Lambda?

After all clientDateTime and time24 are fix values so their difference does not need to be recalculated in every iteration.

Like:

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

This refactor is usually possible if you are trying to compare the stored datetime shifted by a fix timestamp with an other datetime.

vinczemarton
  • 7,756
  • 6
  • 54
  • 86
  • I had this exact situation, and this helped. However, the scope of this solution is very limited to a specific kind of problem. – Zimano Mar 19 '19 at 14:42
  • @Zimano It solves OPs problem without requiring him to change technologies or resort to hacks. If it can be refactored like this then do it, if not then do it like in the accepted answer. – vinczemarton Mar 25 '19 at 15:10
1

The other way, if performance is not the true goal, you can try using AsEnumerable(). So, it would be like

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

Adding AsEnumerable() will convert the SQL query to entity and allows to run .Net functions on them. For more info, check here about AsEnumerable

messed-up
  • 493
  • 4
  • 12