2010-11-10 13 views
85

W mojej aplikacji korzystam z Entity Framework.Linq do EntityFramework DateTime

moim stole

-Article 
-period 
-startDate 

muszę rekordy pasujące =>DateTime.Now > startDate and (startDate + period) > DateTime.Now

Próbowałem ten kod, ale jego teraz pracuje

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

Kiedy uruchomić mój kod następujący wyjątek występuje

LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.

+0

Jakiego rodzaju jest "okres"? 'AddDays' jest niewłaściwą funkcją, jeśli jest' double'. –

+0

okres typu jest int – Yucel

Odpowiedz

160

Podczas korzystania z LINQ do Entity Framework twoje predykaty w klauzuli Where są tłumaczone na SQL. Otrzymujesz ten błąd, ponieważ nie ma tłumaczenia na język SQL dla DateTime.Add(), co ma sens.

Szybkie obejście będzie czytać wyniki pierwszego Jeżeli oświadczenie w pamięci, a następnie użyć LINQ to Objects, aby zakończyć filtrowanie:

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

Można też spróbować metody EntityFunctions.AddDays jeśli jesteś przy użyciu .NET 4.0:

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

Uwaga: W EF 6 to teraz System.Data.Entity.DbFunctions.AddDays.

+32

To niebezpieczne obejście, co się stanie, jeśli ToList() zwróci ogromną ilość danych? –

+0

@Stefan P. - Wtedy pierwsza instrukcja odczytałaby ogromną ilość danych do pamięci. Druga metoda powinna być w porządku, ale jest dostępna tylko w .NET 4.0. –

+6

Dzięki za podpowiedź EntityFunctions.AddDays Używam EF .net 4.0, ale nie wiedziałem o EntityFunctions, zajrzę w to. –

3

Jak o odjęcie 2 dni od DateTime.Now:

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

Szczerze mówiąc, ja nie wiem, co chce osiągnąć, ale to może działać

+0

Artykuły zaczną być pokazywane w StartDate i kończą po x (okresie) dniach. To właśnie próbuję zrobić. Drugie rozwiązanie Justina Niessnera działało bardzo dobrze na to, co chcę zobaczyć: – Yucel

+1

Mam ten sam błąd za pomocą funkcji Subtract! –

71

myślę, że to jest to, co ta ostatnia odpowiedź próbował sugerować, ale zamiast próbować dodać dni do p.startdat (coś, co nie może być przekonwertowany do sql) Dlaczego nie coś, co można porównać do SQL:

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

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

To znacznie lepsza odpowiedź niż zaakceptowana odpowiedź z większą liczbą głosów. Jest prostszy, bezpieczniejszy i bardziej wydajny. –

+1

@Adrian Carr - Może być lepiej dla tego przypadku użycia, ale nie dla tak wielu, jak rozwiązanie 'EntityFunctions'. W tym przypadku drugi argument operacji nie jest pobierany z innego obiektu w zapytaniu i może zostać obliczony przed wysłaniem zapytania. Jeśli oba argumenty zostały znalezione w db, rozwiązanie 'EntityFunctions' nadal będzie odpowiednie, podczas gdy rozwiązanie tej odpowiedzi nie będzie już działać. –

1

Jeśli potrzebujesz przekształcenia wyrażenia na SQL, spróbuj użyć metody:

System.Data.Entity.Core.Objects.AddDays .

Faktycznie jest oznaczony jako przestarzały, ale działa. Powinien zostać zastąpiony przez System.Data.Entity.DbFunctions.AddDays, ale nie mogę go znaleźć ...

+0

To dodaje nic więcej niż zaakceptowana odpowiedź sprzed 4 lat! –

+0

@AndrewHarris również moja odpowiedź to 4 lata temu. W pierwszej wersji odpowiedzi było ToList (=> materializacja danych) przed Where (zobacz pierwszy komentarz odpowiedzi). – bubi

Powiązane problemy