2012-06-06 15 views
6

Chciałbym pobrać wszystkie zapisy z konkretnego dnia, bez względu na to, która godzina jest związana z tymi rekordami. Do tej pory mam metodę tak:Pobieranie rekordów według daty z tylko jednodniowym porównaniem części za pomocą nhibernate

public IQueryable<Record> QueryByDay(DateTime day) 
{ 
    DateTime from = day.Date; 
    DateTime to = day.Date.AddDays(1); 

    return repository.Table 
     .Where(t => t.MyDate >= from && t.MyDate < to); 
    } 

Ale w LINQ-obiektu możemy zrobić (zakładając Tabela jest teraz niektóre kolekcja):

public IEnumerable<Record> QueryByDay(DateTime day) 
{ 
    return repository.Table 
     .Where(t => t.MyDate.Date == day.Date); 
} 

co jest oczywiście bardziej czytelne i czuje się bardziej czyste . Zastanawiam się, czy istnieje lepszy sposób na napisanie pierwszej metody przy użyciu pamięci bazy danych i nhibernate?

+0

Uważam, że forma, której używałeś do L2O, działa dobrze z NH. –

+0

@Diego Mijelshon Czy możesz mi powiedzieć, która wersja NHibernate, której używasz, działa? W projekcie, nad którym pracuję, używamy wersji 2.1, a to rzuca wyjątek NHibernate.QueryException. – 0lukasz0

+1

2.1 ma 3 lata i nie jest obsługiwany. 3.3 jest bieżącym stabilnym wydaniem. –

Odpowiedz

6

Jak powiedział w komentarzach, zapytanie LINQ działa dobrze z NH 3.3.

We wcześniejszych wersjach można użyć HQL:

return session.CreateQuery("from MyClass where date(MyDate) = :day") 
       .SetParameter("day", day.Date) 
       .List<MyClass>(); //executes 

Można również użyć funkcji date z kryteriów, poprzez SQLFunction. Jest to bardziej zawiłe, ale pozwala budować bardziej dynamiczne zapytania:

return session.CreateCriteria<Foo>() 
       .Add(Restrictions.Eq(
         Projections.SqlFunction("date", 
               NHibernateUtil.Date, 
               Projections.Property("MyDate")), 
         day.Date)) 
       .List<MyClass>(); //executes 
2
public IEnumerable<Record> QueryByDay(DateTime day) 
{ 
    return repository.Table 
     .Where(t => t.MyDate.Day == day.Day && t.MyDate.Month == day.Month && t.MyDate.Year == day.Year); 
} 
+0

Czy możesz mi powiedzieć, która wersja NHibernate, której używasz, działa? W projekcie, nad którym pracuję, używamy wersji 2.1, a to rzuca wyjątek NHibernate.QueryException. – 0lukasz0

+1

Oh! v2.1 nie obsługuje Linq, ale istnieje gałąź z dostawcą Linq, z której nie wyszło. Wersja 3+ zawiera macierzystego dostawcę Linq. Jak zauważył @Diego Mihelshon, "2.1 ma 3 lata i jest nieobsługiwany, 3.3 jest obecnie stabilnym wydaniem". – ivowiblo

+0

OK, daję +1, ale jeśli SomeDateAttr.Date == OtherDate.Date działa w NH 3+, to moim zdaniem jest to lepsze podejście. – 0lukasz0

2

To zależy od dostawcy LINQ. Nie jestem pewien, czy dostawca NHibernate LINQ obsługuje składnię item.SomeDateProperty.Date == x i wątpię, aby tak się stało. Ale można zrobić własną metodę rozszerzenia tak:

public static IQueryable<T> FilterByDate(this IQueryable<T> This, Expression<Func<T, DateTime>> getProperty, DateTime date) 
{ 
    DateTime from = day.Date; 
    DateTime to = day.Date.AddDays(1); 
    return This.Where(x=> 
    Expression.And(
     Expression.GreaterThan(getProperty, Expression.Variable(from)), 
     Expression.LessThan(getProperty, Expression.Variable(to))); 

} 

NIE zbuduje drogę to jest teraz - Chciałem tylko dać wyobrażenie o tym, co zrobić.

Następnie można go używać tak:

var result = repository.Table.FilterByDate(x=>x.MyDate, new DateTime(2012, 6,6)); 
+0

+1, podoba mi się pomysł, choć wygląda na bardziej aktualny NHibernate obsługuje najprostsze rozwiązania. – 0lukasz0