2015-06-04 15 views
16

Piszę bardzo, bardzo proste zapytanie, które po prostu pobiera dokument z kolekcji według unikalnego identyfikatora. Po pewnym frusteration (jestem nowy w Mongo i asynchroniczny/czekają model programowania), I zdobione to:Różnica między Find i FindAsync

IMongoCollection<TModel> collection = // ... 
FindOptions<TModel> options = new FindOptions<TModel> { Limit = 1 }; 
IAsyncCursor<TModel> task = await collection.FindAsync(x => x.Id.Equals(id), options); 
List<TModel> list = await task.ToListAsync(); 
TModel result = list.FirstOrDefault(); 
return result; 

To działa, to świetnie! Ale zachować widząc odniesień do „znaleźć” sposób, a ja pracowałem na to uwagę:

IMongoCollection<TModel> collection = // ... 
IFindFluent<TModel, TModel> findFluent = collection.Find(x => x.Id == id); 
findFluent = findFluent.Limit(1); 
TModel result = await findFluent.FirstOrDefaultAsync(); 
return result; 

Jak się okazuje, to też działa, to świetnie!

Jestem pewien, że jest jakiś ważny powód, dla którego mamy dwa różne sposoby osiągnięcia tych wyników. Jaka jest różnica między tymi metodami i dlaczego powinienem wybrać jeden nad drugim?

+1

Słowo kluczowe 'async' pozwala kompilatorowi" zarządzać "twoim kodem poprzez jego harmonogram. Może to zrobić, ale nie zawsze spowoduje, że Twoja aplikacja będzie wielowątkowa. Słowo kluczowe "await" sygnalizuje kompilatorowi dobre punkty decydujące i zmieniające kontekst lub wykorzystujące nowy wątek. – whoisj

+0

'' async' w szczególności _nie_ powoduje, że twoja aplikacja jest wielowątkowa. Zobacz [tutaj] (https://msdn.microsoft.com/en-us/library/hh191443.aspx). To nie jest pytanie o C#, ale różnice w metodach dostępnych z MongoDB C# API. – object88

+0

Co masz na myśli, że 'FindAsync' nie spowoduje, że twoja aplikacja będzie wielowątkowa? Jest duża szansa, że ​​to zrobi, jeśli nie "zaczekasz" od razu. –

Odpowiedz

16

Różnica polega na składni. Find i FindAsync zarówno pozwala zbudować kwerendę asynchroniczną z tej samej wydajności, tylko

FindAsync powraca kursor który nie ładuje wszystkie dokumenty na raz i zapewnia interfejs do pobierania dokumentów jeden po drugim z DB kursora. Jest to pomocne, gdy wynik zapytania jest ogromny.

Find zapewnia Państwu więcej prostą składnię dzięki metodzie ToListAsync gdzie wewnątrz pobiera dokumenty z kursorem i zwrotu wszystkich dokumentów jednocześnie.

+0

Tak więc, w moim konkretnym przypadku, nie ma żadnej skutecznej różnicy, ponieważ ładuję dokładnie jeden dokument w obie strony. W przypadku dużej partii dokumentów, wygląda na to, że chciałbym użyć kursora (i być może nie podążać za nim za pomocą 'ToListAsync', ponieważ wtedy ładowałbym wszystkie dokumenty?). Czy to uczciwa ocena? – object88

+1

Dla jednego dokumentu Znajdź wygląda lepiej, ponieważ nie działa z kursorem. – rnofenko

0

Wyobraź sobie, że wykonujesz ten kod w żądaniu internetowym, wywołując metodę find wątek żądania zostanie zamrożony do czasu, aż baza danych zwróci wyniki, to jest połączenie synchroniczne, jeśli jest to operacja długiej bazy danych, która trwa kilka sekund, będzie miał jeden z dostępnych wątków do obsługi żądania internetowego, nie robiąc nic, po prostu oczekując, że baza danych zwróci wyniki i marnując cenne zasoby (liczba wątków w puli wątków jest ograniczona).

Dzięki FindAsync wątek twojego żądania internetowego będzie wolny podczas oczekiwania bazy danych na zwrócenie wyników, co oznacza, że ​​podczas połączenia z bazą danych ten wątek może wziąć udział w innej prośbie internetowej. Gdy baza danych zwraca wynik, kod kontynuuje wykonywanie.

W przypadku długich operacji, takich jak odczyt/zapis z systemu plików, operacje na bazie danych, komunikowanie się z innymi usługami, dobrym pomysłem jest korzystanie z połączeń asynchronicznych. Ponieważ podczas oczekiwania na wyniki, wątki są dostępne do obsługi innego żądania internetowego. Jest to bardziej skalowalne.

Zobacz ten artykuł w witrynie microsoft https://msdn.microsoft.com/en-us/magazine/dn802603.aspx.

+2

Obie części kodu są jednak asynchroniczne. W pierwszym przykładzie są dwa oczekiwania: jeden na FindAsync i jeden na ToListAsync. W drugim czeka na Ciebie: na FirstOrDefaultAsync. To, co chciałbym wiedzieć, to nie tyle korzyści z asynchronizacji/czekania (rozumiem), ale raczej, jakie są potencjalnie blokujące części różnych ścieżek kodu? Czy istnieją okoliczności, w których lepiej jest używać FindAsync i ToListAsync, a FirstOrDefaultAsync? – object88

+0

Czy działa ten kod? Z find nie jest konieczne toList, ponieważ po prostu zwraca pierwszy znaleziony obiekt https://msdn.microsoft.com/en-us/library/x0b5b5bc%28v=vs.110%29.aspx –

+0

Rozwinąłem trochę kod wyjaśnić pytanie. – object88

Powiązane problemy