LINQ에서 SQL이 연장 방법으로 속이는 이유는 무엇입니까? 지금 뭐야?
-
03-07-2019 - |
문제
내 고려하십시오 Event
클래스, 그리고 나는 저장합니다 DateTime
UTC 날짜로 DB에 있습니다. 특정 시간대의 현재 날짜를 기준으로 필터링 범위를 반환하고 싶습니다.
이것은 잘 작동합니다 :
IQueryable<Event> test1 = this.GetSortedEvents().Where(e => e.FinishDateTime.Date >= DateTime.UtcNow.Date);
이것은 또한 잘 작동합니다.
IQueryable<Event> test2 = this.GetSortedEvents().Where(e => e.FinishDateTime.AddHours(3).Date >= DateTime.UtcNow.AddHours(3).Date);
.. 그리고 내 시간대 요구 사항을 추가로 충족합니다.
그래서 여기서는이 특정 변환을이 확장 방법으로 옮길 수 있다고 생각합니다.
public static DateTime RiyadhTimeFromUtc(this DateTime utcTime) { return utcTime.AddHours(3); }
이것은 작동하지 않습니다.
IQueryable<Event> test3 = this.GetSortedEvents().Where(e => e.FinishDateTime.RiyadhTimeFromUtc().Date >= DateTime.UtcNow.RiyadhTimeFromUtc().Date);
.
동일한 코드가 확장 방법에 없을 때 컴파일러가 행복하게 SQL로 변환했기 때문에 이것은 분명히 쓰레기입니다.
특정 유형과 가장 최근에 DateTime을 사용하기 전에 "SQL에 대한 번역이 없음"문제가 발생합니다. 그러나 위의 내 테스트 이 링크 AddHours 방법이 SQL 번역에서 지원되어야 함을 증명하십시오.
누군가 내가 여기서 내가 잘못하고있는 일을 말해 줄 수 있다면 (또는이 문제에 대한 다른 해결 방법 접근법) 정말 감사 할 것입니다.
해결책
표현 트리 측면에서 생각해야합니다. 이것이 Linq-to-SQL이 쿼리를 SQL로 전환하는 방법입니다.
나무를 검사 할 때 a DateTime
개체 한 다음 호출 된 방법이 지원되는 방법 중 하나인지 확인합니다 (Add
, AddHours
, 메소드를 직접 사용하면 정상적으로 작동합니다.
다른 확장 방법을 사용하면 해당 방법의 본문에 대한 정보가 표현식 트리에 있지 않기 때문에 그 방법을 볼 수 없습니다. IL에 숨겨져 있습니다. 따라서 LINQ-to-SQL이 내용이 무엇인지 알아낼 수 없기 때문에 확장 방법의 내용이 지원되는지 여부는 중요하지 않습니다.
방법을 생성하는 요점은 캡슐화 및 정보 숨기기입니다. 일반적으로 응용 프로그램 개발에서 잘 작동하지만 불행히도 여기에서는 정보를 볼 수 있어야하는 LINQ-to-SQL의 정보를 숨기고 있습니다.
편집 된 질문에 대한 응답으로 - 이것을 어떻게 해결합니까? LINQ 표현식 내에서 날짜 계산을 유지하려면 쿼리를 효율적으로 유지하기 위해 할 수있는 유일한 일은 확장 방법을 사용하지 않고 사용하는 것입니다. AddHours(3)
직접 DateTime
물체.
LINQ의 불행한 한계 중 하나입니다. 많은 것들과 마찬가지로 다양한 소스에 대한 공통 구문을 제공하는 동안 소스의 공급자가 지원할 수있는 운영에 대한 제한 사항과 제한 사항이 다소 유출 된 추상화입니다. -표현 트리를 실행하기 위해 번역 할 필요가 없으므로 객체.
다른 팁
LINQ-to-SQL이 그것을 알아낼 수있는 것 같습니다. RiyadhTimeFromUtc
정말 전화였습니다 AddHours(3)
코드에 대한 매우 정교한 분석을 수행해야합니다. 당신이 썼다고 말하면
public static DateTime RiyadhTimeFromUtc(this DateTime utcTime)
{
if (Random.GetInt() < 99) {
return utcTime.AddHours(3);
} else {
return utcTime.AddDays(5);
}
}
SQL로 어떻게 번역할까요? 보다 이 토론 더 많은 정보를 얻으려면.