Lepszy sposób na odpytywanie strony danych i uzyskanie całkowitej liczby w ramach entity Framework 4.1?
Obecnie, gdy muszę uruchomić zapytanie, które będzie używane w / paging robię to coś takiego:
//Setup query (Typically much more complex)
var q = ctx.People.Where(p=>p.Name.StartsWith("A"));
//Get total result count prior to sorting
int total = q.Count();
//Apply sort to query
q = q.OrderBy(p => p.Name);
q.Select(p => new PersonResult
{
Name = p.Name
}.Skip(skipRows).Take(pageSize).ToArray();
To działa, ale zastanawiałem się, czy jest możliwe, aby poprawić to, aby być bardziej wydajnym, nadal używając linq? Nie mogłem wymyślić sposobu, aby połączyć liczbę z pobieraniem danych w jednej podróży do DB bez użycia zapisanego proc.
3 answers
Poniższe zapytanie otrzyma liczbę i wyniki stron w jednej podróży do bazy danych, ale jeśli sprawdzisz SQL w LINQPad, zobaczysz, że nie jest zbyt ładny. Mogę sobie tylko wyobrazić, jak to będzie wyglądać dla bardziej złożonego zapytania.
var query = ctx.People.Where (p => p.Name.StartsWith("A"));
var page = query.OrderBy (p => p.Name)
.Select (p => new PersonResult { Name = p.Name } )
.Skip(skipRows).Take(pageSize)
.GroupBy (p => new { Total = query.Count() })
.First();
int total = page.Key.Total;
var people = page.Select(p => p);
Dla prostego zapytania Jak to, prawdopodobnie można użyć jednej metody (2 wycieczki do bazy danych, lub za pomocą GroupBy
, aby zrobić to w 1 podróży) i nie zauważyć dużej różnicy. Myślę, że w przypadku skomplikowanych procedur, najlepszym rozwiązaniem byłaby procedura składowana.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-14 17:26:31
Sugeruję wykonanie dwóch zapytań dla pierwszej strony, jednego dla całkowitej liczby i jednego dla pierwszej strony lub wyników.
Buforuj całkowitą liczbę do użycia podczas przechodzenia poza pierwszą stronę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-10 20:34:46
Odpowiedź Jeffa Ogaty może być trochę zoptymalizowana.
var results = query.OrderBy(p => p.Name)
.Select(p => new
{
Person = new PersonResult { Name = p.Name },
TotalCount = query.Count()
})
.Skip(skipRows).Take(pageSize)
.ToArray(); // query is executed once, here
var totalCount = results.First().TotalCount;
var people = results.Select(r => r.Person).ToArray();
To robi prawie to samo, tylko że nie będzie przeszkadzać bazie danych z niepotrzebną grupą by. Jeśli nie jesteś pewien, czy Twoje zapytanie będzie zawierać co najmniej jeden wynik i nie chcesz, aby kiedykolwiek wyrzuciło wyjątek, możesz uzyskać totalCount
w następujący (aczkolwiek mniej czystszy) sposób:
var totalCount = results.FirstOrDefault()?.TotalCount ?? 0;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-26 15:57:55