FirstOrDefault roznica w wywołaniu.

0

Czym beda róznic się ponizsze wywołania. Zwracają to samo, ale czy jest jakas róznica w działaniu? Czy są jakies powody aby preferowac raczej jeden z tych zapiso, ktory?

Person person = repository.People.Where(p=>p.Age==age).FirstOrDefault();
Person person = repository.People.FirstOrDefault(p=>p.Age==age);
1

Jeżeli chodzi o SQL, to w EF Core na MSSQL oba generują ten sam SQL.

SELECT TOP(1) ...
FROM ... AS [x]
WHERE ...

Według tego (4 lata temu) podobno

https://stackoverflow.com/questions/8059285/c-sharp-linq-whereexpression-firstordefault-vs-firstordefaultexpression/8059482

I started getting "The wait operation timed out." using Where(query).FirstOrDefault() on a large dataset. When I changed it to FirstOrDefault(query) I stopped seeing it; so maybe there's something to this answer. Regardless, the code is slightly nicer to read.

Chociaż skacząc debuggerem w obu przypadkach po znalezieniu pierwszego spełniającego predykat obiektu następuje koniec, więc chyba nie ma różnicy, aczkolwiek druga opcja jest przejrzystsza i krótsza.

1

Jeśli widzę pierwszy zapis, to zakładam, że autor nie zna LINQ (no bo jak inaczej wyjaśnić dłuższy zapis?), więc nie powinno się go przyjmować do pracy, a jeśli już pracuje, bacznie sprawdzać każdy PR.

0

somekind,
gdzieś czytałem (SO) że użycie Where(x=>...) a potem FirstOrDefault() jest szybsze, niż FirstOrDefault(x=> ...)
Nie pamiętam jednak czy dotyczyło to ORM-a, czy jakiegoś konkretnego większego zapytania

0

Nie rozumiem, jak Where().FirstOrDefault() może być szybsze, jeśli musi sprawdzić wszystkie elementy, czego wersja z FirstOrDefault() nie robi.

Chyba że mówimy o jakimś specyficznym providerze LINQ, ale to już raczej wina tego providera że jest zaimplementowany w sposób ułomny.

A jednak źle myślałem, bo .Where().FirstOrDefault() nie przejdzie wszystkich elementów. Zachowa się tak jak sam FirstOrDefault() z warunkiem.

0

Nie chce mi się zaglądać do kodu, ale podejrzewam, że parametrowe FirstOrDefault robi coś takiego (pseudokod):

return this.Where(predicate).FirstOrDefault();

1
Azarien napisał(a):

Nie chce mi się zaglądać do kodu, ale podejrzewam, że parametrowe FirstOrDefault robi coś takiego (pseudokod):

return this.Where(predicate).FirstOrDefault();

To by było bardzo nieoptymalne, więc ani Enumerable.FirstOrDefault ani Queryable.FirstOrDefault tego nie robią. To pierwsze iteruje po elementach kolekcji i zwraca pierwszy element, który spełnia warunek, a drugie jest tłumaczone na SQL w jakiś tam zdefiniowany przez provider sposób.

0

Jeżeli chodzi o EF Core(SQL Server) to jest taka różnica:

var fName = _context.People.FirstOrDefault(x => x.Age > 30).FirstName;

var fName2 = _context.People.Where(x => x.Age > 30).Select(x => x.FirstName).FirstOrDefault();

W wynikowym SQLu przy pierwszym zapisie pobierany jest cały model bez relacji, a w drugim tylko FirstName

SELECT TOP(1) 
[x].[Id], [x].[AccessFailedCount], [x].[ConcurrencyStamp] , [x].[Email], [x].[EmailConfirmed], [x].[LockoutEnabled], [x].[LockoutEnd], [x].[NormalizedEmail], [x].[NormalizedUserName], [x].[PasswordHash], [x].[PhoneNumber], [x].[PhoneNumberConfirmed], [x].[SecurityStamp], [x].[TwoFactorEnabled], [x].[UserName], [x].[Age], [x].[FirstName]
FROM [AspNetUsers] AS [x]
WHERE ([x].[Age] > 30)

SELECT TOP(1) [x].[FirstName] 
FROM [AspNetUsers] AS [x] 
WHERE [x].[Age] > 30

Czyli dłuższy zapis jest lepszy pod względem tego co wychodzi z bazy.

0

Raczej nic dziwnego, bo to są dwie zupełnie inne zapytania - w drugim robisz projekcję, w pierwszym nie. Jak w obu przypadkach zrobisz to samo, to SQL pewnie też wyjdzie taki sam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1