web-dev-qa-db-ja.com

DbArithmeticExpressionの引数には、共通の数値型が必要です

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.

助けてください!

112

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より前.

229
Gert Arnold

これは古い質問であることを知っていますが、特定のケースでは@GertArnoldが示唆するDBFunctionsを使用する代わりに、操作を反転させるだけでラムダから問題の算術演算を削除できませんか?

結局clientDateTimetime24は修正値であるため、繰り返しごとに差を再計算する必要はありません。

のような:

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

通常、このリファクタリングは、修正タイムスタンプによってシフトされた保存日時を他の日時と比較しようとしている場合に可能です。

2
SoonDead

別の方法として、パフォーマンスが真の目標でない場合は、AsEnumerable()を使用して試すことができます。だから、それは次のようになります

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

AsEnumerable()を追加すると、SQLクエリがエンティティに変換され、それらに対して.Net関数を実行できるようになります。詳細については、こちらをご覧ください about AsEnumerable

1
messed-up