[C#] 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.

도와주세요!



답변

DateTimeEntity Framework 6 이하에서는 산술 연산 이 지원되지 않습니다. DbFunctions * 를 사용해야 합니다. 따라서 진술의 첫 번째 부분은 다음과 같습니다.

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

DiffHours메서드는 Nullable<DateTime>.

Entity Framwork 코어 (Sql Server, 아마도 다른 DB 공급자와 함께 사용되는 경우)는 DateTime AddXxx함수 (예 :)를 지원합니다 AddHours. 그들은 DATEADDSQL 로 번역됩니다 .

* EntityFunctionsEntity Framework 버전 6 이전


답변

나는 이것이 오래된 질문이라는 것을 알고 있지만 DBFunctions@GertArnold가 제안한 것처럼 사용 하는 대신 특정 경우 에 작업을 반전하여 Lambda에서 문제의 산술을 이동할 수 없습니까?

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

이 리팩터링은 일반적으로 수정 타임 스탬프에 의해 이동 된 저장된 날짜 시간을 다른 날짜 시간과 비교하려는 경우 가능합니다.


답변

다른 방법으로 성능이 진정한 목표가 아닌 경우 AsEnumerable(). 그래서 그것은

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

AsEnumerable ()을 추가하면 SQL 쿼리가 엔티티로 변환되고 여기에서 .Net 함수를 실행할 수 있습니다. 자세한 내용 은 AsEnumerable에 대해 여기 확인하십시오.


답변