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();
このLinq式は、次の例外をスローします。
DbArithmeticExpression arguments must have a numeric common type.
助けてください!
DateTime
を使用した演算は、Entity Framework 6以前ではサポートされていません。 DbFunctions *を使用する必要があります。したがって、ステートメントの最初の部分では、次のようになります。
var sleeps = context.Sleeps(o =>
DbFunctions.DiffHours(o.ClientDateTimeStamp, clientDateTime) < 24);
DiffHours
メソッドはNullable<DateTime>
。
Entity Framwork core(SQL Serverで使用される場合、他のDBプロバイダーも使用可能)は、DateTime AddXxx
関数(AddHours
など)をサポートします。 SQLでDATEADD
に変換されます。
* EntityFunctions
Entity Frameworkバージョン6より前.
これは古い質問であることを知っていますが、特定のケースでは@GertArnoldが示唆するDBFunctions
を使用する代わりに、操作を反転させるだけでラムダから問題の算術演算を削除できませんか?
結局clientDateTime
とtime24
は修正値であるため、繰り返しごとに差を再計算する必要はありません。
のような:
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();
通常、このリファクタリングは、修正タイムスタンプによってシフトされた保存日時を他の日時と比較しようとしている場合に可能です。
別の方法として、パフォーマンスが真の目標でない場合は、AsEnumerable()
を使用して試すことができます。だから、それは次のようになります
List<Model.Sleep> sleeps = context.Sleeps.AsEnumerable().Where(....
AsEnumerable()を追加すると、SQLクエリがエンティティに変換され、それらに対して.Net関数を実行できるようになります。詳細については、こちらをご覧ください about AsEnumerable