Linq에서 EntityFramework DateTime으로


108

내 응용 프로그램에서 Entity Framework를 사용하고 있습니다.

내 테이블

-Article
-period
-startDate

일치하는 레코드가 필요합니다 => DateTime.Now > startDate and (startDate + period) > DateTime.Now

이 코드를 시도했지만 이제 작동합니다.

Context.Article
    .Where(p => p.StartDate < DateTime.Now)
    .Where(p => p.StartDate.AddDays(p.Period) > DateTime.Now)

내 코드를 실행할 때 다음 예외가 발생합니다.

LINQ to Entities는 'System.DateTime AddDays (Double)'메서드를 인식하지 않으며이 메서드는 저장소 식으로 변환 할 수 없습니다.


어떤 유형 period입니까? AddDays이 경우 잘못된 함수 double입니다.
Craig Stuntz

답변:


201

LINQ to Entity Framework를 사용하는 경우 Where 절 내의 조건자가 SQL로 변환됩니다. DateTime.Add()의미 가 있는 SQL 로의 번역이 없기 때문에 오류가 발생합니다 .

빠른 해결 방법은 첫 번째 Where 문의 결과를 메모리로 읽은 다음 LINQ to Objects를 사용하여 필터링을 완료하는 것입니다.

Context.Article.Where(p => p.StartDate < DateTime.Now)
               .ToList()
               .Where(p => p.StartDate.AddDays(p.Period) > DateTime.Now);

.NET 4.0을 사용하는 경우 EntityFunctions.AddDays 메서드를 사용해 볼 수도 있습니다 .

Context.Article.Where(p => p.StartDate < DateTime.Now)
               .Where(p => EntityFunctions.AddDays(p.StartDate, p.Period)
                   > DateTime.Now);

참고 : EF 6현재 System.Data.Entity.DbFunctions.AddDays.


42
이것은 위험한 해결 방법입니다. ToList ()가 엄청난 양의 데이터를 반환하면 어떻게됩니까?
Stefan P.

7
EntityFunctions.AddDays 팁에 감사드립니다. EF .net 4.0을 사용하고 있지만 EntityFunctions에 대해 몰랐습니다.
Stefan P.

2
@SaeedAlg-첫 번째 예에서는 항목을 메모리로 읽어야합니다. 두 번째 예에서는 원래 형식과 일치하도록 두 개의 Where 절을 유지했습니다. 둘을 단일 Where 절로 압축하더라도 Entity Framework는 ID SQL을 생성하므로 실제로는 가독성의 문제입니다.
Justin Niessner 2010

2
@Justin Niessner 덕분에 아주 많이, 나는 그 4 시간 동안, 당신은 내 인생의 선방 덕분에 다시 초에 할 노력하고 있어요
YUCEL

2
EF로 "빠른"해결 방법을 제공 할 때 우리 모두는 ToList 및 ToArray 메서드 사용을 피해야합니다. 이전에 날짜를 계산하고 해당 값과 비교하는 것도 빠르며 결과를 메모리에 인스턴스화하지 않고 EF 쿼리에서 작동합니다.
Isaac Llopis 2015 년

92

나는 이것이 마지막 대답이 제안하려고 한 것이라고 생각하지만 p.startdat (sql 문으로 변환 할 수없는 것)에 날을 추가하려고하기보다는 sql과 동일 할 수있는 일을하지 않는 이유는 무엇입니까?

var baselineDate = DateTime.Now.AddHours(-24);

something.Where(p => p.startdate >= baselineDate)

2
@Adrian Carr-이 사용 사례에는 더 좋을 수 있지만 EntityFunctions솔루션 만큼 많지는 않습니다 . 여기에서 두 번째 피연산자는 쿼리의 다른 엔터티에서 검색되지 않으며 쿼리 전에 계산할 수 있습니다. 두 피연산자가 db에서 발견되면 EntityFunctions솔루션은 여전히 ​​적합하지만이 응답의 솔루션은 더 이상 작동하지 않습니다.
Frédéric

이것은 답으로 표시된 솔루션보다 더 나은 솔루션입니다. Justin / 표시된 답변의 응답은 데이터베이스에서 불필요한 결과를 반환합니다. 이 솔루션은 실제로 필터가있는 SQL에서 날짜를 보내고 SQL을 사용하여 데이터를 필터링하므로 훨씬 더 성능이 좋습니다.
Paul

3

DateTime에서 2 일을 빼는 방법은 다음과 같습니다.

Context.Article
.Where(p => p.StartDate < DateTime.Now)
.Where(p => p.StartDate > DateTime.Now.Subtract(new TimeSpan(2, 0, 0, 0)))

솔직히 말해서 당신이 무엇을 성취하려고하는지 잘 모르겠지만이게 효과가있을 수 있습니다


기사는 StartDate에 표시되기 시작하고 x (기간) 일 후에 종료됩니다. 이것이 내가하려는 것입니다. 저스틴 Niessner의 두 번째 솔루션은 내가보고 싶은 아주 잘 작동
YUCEL

3

표현식을 SQL로 변환해야하는 경우 다음을 사용할 수 있습니다.

System.Data.Entity.Core.Objects.AddDays 메서드.

실제로 사용되지 않는 것으로 표시되지만 작동합니다. System.Data.Entity.DbFunctions.AddDays로 바꿔야하지만 찾을 수 없습니다 ...


이것은 4 년 전에 받아 들여진 대답에 지나지 않습니다!
Andrew Harris

@AndrewHarris도 내 대답은 4 년 전 대답입니다. 답변의 첫 번째 버전에는 Where 앞에 ToList (=> 데이터 구체화)가있었습니다 (답변의 첫 번째 주석 참조).
bubi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.