EF에서 DateTime의 날짜 구성 요소 만 비교하는 방법은 무엇입니까?


116

두 개의 날짜 값이 있는데 하나는 이미 데이터베이스에 저장되어 있고 다른 하나는 DatePicker를 사용하여 사용자가 선택했습니다. 유스 케이스는 데이터베이스에서 특정 날짜를 검색하는 것입니다.

이전에 데이터베이스에 입력 한 값은 항상 12:00:00의 시간 구성 요소를 가지며 선택기에서 입력 한 날짜는 다른 시간 구성 요소를 갖습니다.

날짜 구성 요소에만 관심이 있고 시간 구성 요소를 무시하고 싶습니다.

C #에서이 비교를 수행하는 방법은 무엇입니까?

또한 LINQ에서이 작업을 수행하는 방법은 무엇입니까?

업데이트 : LINQ to Entities에서 다음이 제대로 작동합니다.

e => DateTime.Compare(e.FirstDate.Value, SecondDate) >= 0

1
이 SO 질문을 살펴볼 수도 있습니다. stackoverflow.com/questions/683037/how-to-compare-dates-in-c/…
Quintin Robinson

답변:


121

참고 : 이 답변을 작성할 당시에는 EF- 관계가 명확하지 않았습니다 (작성된 후 질문으로 편집 됨). EF에 대한 올바른 접근 방식은 Mandeeps answer를 확인하십시오 .


DateTime.Date속성을 사용하여 날짜 만 비교를 수행 할 수 있습니다 .

DateTime a = GetFirstDate();
DateTime b = GetSecondDate();

if (a.Date.Equals(b.Date))
{
    // the dates are equal
}

34
날짜를 비교하는 것은 쉽지만 질문은 .Date 속성을 SQL로 변환 할 수없는 LINQ to Entities와 관련이 있습니다.
Michaël Carpentier

1
@ MichaëlCarpentier : 좋은 지적입니다. 분명히 그것은 여전히 ​​OP의 문제를 해결했습니다.
Fredrik Mörk 2013 년

6
이것은 데이터베이스를 쿼리하는 것이 아니라 사실 후에 CLR / 애플리케이션 계층의 데이터를 처리합니다. 실제 해결책은 아래 답변에 지정된대로 EntityFunctions.TruncateTime (..) 함수를 사용하는 것입니다. 쿼리를 데이터베이스로 보내고 스토리지 계층에서 처리를 수행 할 수 있기 때문입니다. 이것이 없으면 Where / Count 절에서 날짜 비교 논리를 사용한 다음 필터링 된 데이터에 대한 추가 쿼리를 수행 할 수 없습니다. 먼저 부분 결과를 응용 프로그램 계층으로 가져와야하므로 다음과 같은 시나리오에서 거래를 중단 할 수 있습니다. 대량의 데이터를 처리합니다.
Marchy

6
@Marchy 예, EntityFunctions.TruncateTime확실히 요즘 갈 길인 것 같습니다 (이 질문이 제기 된 다음 해에 출시 된 .NET 4에서 사용할 수있게되었습니다).
Fredrik Mörk 2013 년

1
System.Data.Entity.DbFunctions.TruncateTime () 메서드를 사용하십시오. EntityFramework에 대한 참조를 추가해야합니다
adeel41

132

EntityFunctions시간 부분을 다듬기 위해 수업 을 사용하십시오 .

using System.Data.Objects;    

var bla = (from log in context.Contacts
           where EntityFunctions.TruncateTime(log.ModifiedDate) ==  EntityFunctions.TruncateTime(today.Date)
           select log).FirstOrDefault();

출처 : http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/84d4e18b-7545-419b-9826-53ff1a0e2a62/

최신 정보

EF 6.0 이상 EntityFunctions 현재로 대체 DbFunctions .


37
(적어도) EF6 EntityFunctionsSystem.Data.Entity.DbFunctions위해 메모 만 사용되지 않습니다 . 이보다 이전 일 수 있습니다.
pquest 2014 년

4
: 그것은 천천히 정말 더 많은 정보이기 때문에 나는이 솔루션에 뛰어 빨리되지 않을 것 stackoverflow.com/questions/22776843/...
pajics을

SQLite 데이터베이스에서 작동하지 않는 것 같습니다. "SQL 논리 오류 또는 누락 된 데이터베이스 없음 해당 함수 : TruncateTime"이 표시됩니다.
shadowsora

24

이것이 당신을 도울 수 있다고 생각합니다.

EF 데이터로 채워진 리포지토리의 날짜를 비교해야하므로 .Date는 LinqToEntities 번역에서 구현되지 않았기 때문에 옵션이 아니 었습니다.

다음은 코드입니다.

        /// <summary>
    /// Check if two dates are same
    /// </summary>
    /// <typeparam name="TElement">Type</typeparam>
    /// <param name="valueSelector">date field</param>
    /// <param name="value">date compared</param>
    /// <returns>bool</returns>
    public Expression<Func<TElement, bool>> IsSameDate<TElement>(Expression<Func<TElement, DateTime>> valueSelector, DateTime value)
    {
        ParameterExpression p = valueSelector.Parameters.Single();

        var antes = Expression.GreaterThanOrEqual(valueSelector.Body, Expression.Constant(value.Date, typeof(DateTime)));

        var despues = Expression.LessThan(valueSelector.Body, Expression.Constant(value.AddDays(1).Date, typeof(DateTime)));

        Expression body = Expression.And(antes, despues);

        return Expression.Lambda<Func<TElement, bool>>(body, p);
    }

이런 식으로 사용할 수 있습니다.

 var today = DateTime.Now;
 var todayPosts = from t in turnos.Where(IsSameDate<Turno>(t => t.MyDate, today))
                                      select t);

10

DateDB 엔터티에 속성을 사용하면 예외가 발생합니다.

"The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."

다음과 같이 사용할 수 있습니다.

  DateTime date = DateTime.Now.Date;

  var result = from client in context.clients
               where client.BirthDate >= date
                     && client.BirthDate < date.AddDays(1)
               select client;

8

LINQ to Entities에서이를 수행하려면 지원되는 메서드 를 사용해야 합니다 .

var year = someDate.Year;
var month = ...
var q = from r in Context.Records
        where Microsoft.VisualBasic.DateAndTime.Year(r.SomeDate) == year 
              && // month and day

추악하지만 작동하며 DB 서버에서 수행됩니다.


8

여기에 다른 방법이 있지만 SecondDate가 전달하는 변수 인 경우에만 유용합니다.

DateTime startDate = SecondDate.Date;
DateTime endDate = startDate.AddDays(1).AddTicks(-1);
...
e => e.FirstDate.Value >= startDate && e.FirstDate.Value <= endDate

작동해야한다고 생각합니다


1
우수한. 나를 위해 일했습니다. DateTime = x.Date;내가 놓친 것은 명백한 것이었다. 을 사용 var했거나 비교에 인라인 값이있는 경우보고 된 예외와 함께 실패했습니다. 감사.
Tim Croydon

잘됐다, 팀. 응답이 지연되어 죄송합니다. 실제로 한동안 SO에 로그인하지 않았습니다.
John Kaster 2012 년

1
당신이 변경하는 경우 e.FirstDate.Value <= endDatee.FirstDate.Value < endDate당신에게를 제거 할 수 있습니다 .AddTicks(-1).
Marco de Zeeuw

@MarcodeZeeuw 당신 말이 맞아요. 표시된 조건식은 정확한 시작 및 종료 날짜 시간의 포괄적 인 날짜 비교를위한 것입니다 (날짜 범위 값이 코드 조각에 설정되지 않고 조건에 전달된다고 가정). IOW, 조건은 날짜 시간 값과 별개로 간주됩니다. .
John Kaster 2015 년

6

이것을 사용할 수도 있습니다.

DbFunctions.DiffDays(date1, date2) == 0


4

이를 위해 DbFunctions.TruncateTime () 메서드를 사용할 수 있습니다.

e => DbFunctions.TruncateTime(e.FirstDate.Value) == DbFunctions.TruncateTime(SecondDate);

3

전체 날짜 시간 대신 항상 DateTime 의 Date 속성을 비교하십시오 .

LINQ 쿼리를 만들 때 쿼리에 date.Date를 사용합니다.

var results = from c in collection
              where c.Date == myDateTime.Date
              select c;

10
"지정된 형식 멤버 'Date'는 LINQ to Entities에서 지원되지 않습니다. 이니셜 라이저, 엔터티 멤버 및 엔터티 탐색 속성 만 지원됩니다."라는 오류가 표시됩니다. 이견있는 사람?
pencilslate

예-제공자는 .Date 속성을 직접 처리하지 않습니다. 그것을 꺼내서 나중에 날짜를 비교해야 할 것입니다.
Reed Copsey

.Date는 Linq To Entities에서 사용할 수 없습니다. MS가 곧 오버로드 지원을 추가하기를 바랍니다
John Kaster 2011

1
항상 Date 속성을 비교 하시겠습니까? 나는 이것이 모범 사례인지 궁금했기 때문에이 주석을 봤습니다. 하기 위해 항상 날짜 속성, 같은 심지어의 것을 사용 candidate.Date >= base.Date. 이론적으로 candidate.Date시간은 12:00:00 이상이어야하므로 Date 속성을 사용하는 것은 불필요하지만 Reed의 조언을 고수하겠습니다.
스티븐 호스 킹

3

이것이 내가하는 방법이다.

DateTime date_time_to_compare = DateTime.Now;
//Compare only date parts
context.YourObject.FirstOrDefault(r =>
                EntityFunctions.TruncateTime(r.date) == EntityFunctions.TruncateTime(date_to_compare));

2

// Linq 사용자 / 코더를위한 참고 사항

이렇게하면 사용자 (예 : 날짜 선택기)의 입력으로 작업 할 때 날짜가 범위 내에 있는지 확인하기위한 정확한 비교를 제공해야합니다.

((DateTime)ri.RequestX.DateSatisfied).Date >= startdate.Date &&
        ((DateTime)ri.RequestX.DateSatisfied).Date <= enddate.Date

여기서 startdate 및 enddate는 날짜 선택기의 값입니다.


1

다음과 같이 시도하는 것보다 시간이 없습니다.

TimeSpan ts = new TimeSpan(23, 59, 59);
toDate = toDate.Add(ts);
List<AuditLog> resultLogs = 
    _dbContext.AuditLogs
    .Where(al => al.Log_Date >= fromDate && al.Log_Date <= toDate)
    .ToList();
return resultLogs;

1

아래 링크를 사용하여 시간없이 두 날짜를 비교할 수 있습니다.

private bool DateGreaterOrEqual(DateTime dt1, DateTime dt2)
        {
            return DateTime.Compare(dt1.Date, dt2.Date) >= 0;
        }

private bool DateLessOrEqual(DateTime dt1, DateTime dt2)
        {
            return DateTime.Compare(dt1.Date, dt2.Date) <= 0;
        }

Compare 함수는 3 개의 다른 값을 반환합니다. -1 0 1은 dt1> dt2, dt1 = dt2, dt1을 의미합니다.


DateTime.Compare (dt1.Date, dt2.Date)를 반환하지 않는 이유는 무엇입니까? 이것은 당신이 필요한 모든 것을 만듭니다.
Johnny Graber

0

시도해보세요 ... 두 개의 DateTimes 유형간에 Date 속성을 비교하는 것이 잘 작동합니다.

추신. 임시 방편 솔루션이며 정말 나쁜 습관입니다. 데이터베이스가 수천 개의 레코드를 가져올 수 있다는 것을 알고있을 때는 절대 사용해서는 안됩니다.

query = query.ToList()
             .Where(x => x.FirstDate.Date == SecondDate.Date)
             .AsQueryable();

1
추신 : 일반적으로 DateTimes에 시간 값이 있고 날짜 만 비교하고 싶을 때이 방법을 사용합니다.
Raskunho

2
이것은 매우 나쁜 솔루션입니다. 쿼리는 모든 레코드를 가져온 다음 날짜 만 필터링합니다. 데이터베이스에 수백만 개의 레코드가있는 경우 모든 레코드를 가져 와서 날짜를 필터링합니다. 아주 나쁜 관행.
Dementic

1
임시 방편 솔루션이며 정말 나쁜 습관입니다. 데이터베이스가 수천 개의 레코드를 가져올 수 있다는 것을 알고있을 때는 절대 사용해서는 안됩니다.
Raskunho

귀하의 답변에 귀하의 의견을 추가하면 내 반대 투표를 제거하겠습니다. 이 페이지를 방문하는 모든 사람에게 귀하가 제안한 솔루션이 의견을 읽지 않고도 나쁘다는 것을 분명히 알 수 있어야합니다.
Dementic

일반적으로 나쁜 생각이지만이 접근 방식은 EF가 날짜 비교를 SQL로 변환하는 멍청한 방식으로 인해 작은 레코드 세트 (<1000 레코드 정도)의 성능을 크게 향상시킵니다. SQL EF가 생성하는 것이 아니라 메모리에서 날짜 비교를 수행하는 것만으로도 쿼리가 1 분에서 1 초 미만으로 이동하는 것을 보았습니다.
Extragorey
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.