Entity Framework 4 Single () vs First () vs FirstOrDefault ()


119

Tôi đang có một thời gian tìm kiếm sự so sánh của các cách khác nhau để truy vấn cho một mục duy nhất và khi nào nên sử dụng từng mục.

Có ai có một liên kết so sánh tất cả những điều này, hoặc một lời giải thích nhanh về lý do tại sao bạn sẽ sử dụng một liên kết này? Vẫn còn nhiều nhà khai thác mà tôi không biết?

Cảm ơn bạn.

Câu trả lời:


205

Dưới đây là tổng quan về các phương pháp khác nhau:

  • Tìm () - khi bạn muốn lấy một mục bằng khóa chính. Điều này sẽ trả về null nếu nó không thể tìm thấy một mục. Nó sẽ xem xét ngữ cảnh trước khi đi đến cơ sở dữ liệu (như được chỉ ra bởi Yaron trong các bình luận) có thể là một yếu tố hiệu quả quan trọng nếu bạn cần nhận được cùng một thực thể nhiều lần trong khi cùng một bối cảnh.

  • Single () - khi bạn mong đợi chính xác một mục được trả về bởi một truy vấn. Điều này sẽ đưa ra một ngoại lệ nếu truy vấn không trả về chính xác một mục.

  • SingleOrDefault () - khi bạn mong đợi 0 hoặc một mục được trả về bởi một truy vấn (nghĩa là bạn không chắc chắn liệu một mục có khóa đã cho có tồn tại hay không). Điều này sẽ đưa ra một ngoại lệ nếu truy vấn không trả về 0 hoặc một mục.

  • Đầu tiên () - khi bạn mong đợi một hoặc nhiều mục được trả về bởi một truy vấn nhưng bạn chỉ muốn truy cập vào mục đầu tiên trong mã của mình (việc đặt hàng có thể quan trọng trong truy vấn tại đây). Điều này sẽ đưa ra một ngoại lệ nếu truy vấn không trả về ít nhất một mục.

  • FirstOrDefault () - khi bạn mong đợi 0 hoặc nhiều mục được trả về bởi một truy vấn nhưng bạn chỉ muốn truy cập vào mục đầu tiên trong mã của mình (tức là bạn không chắc có tồn tại một mục có khóa đã cho không)


1
Nó phụ thuộc vào kịch bản. Nếu bạn biết bạn nên luôn lấy lại một bản ghi từ db, không hơn, không kém, đối với một truy vấn đã cho thì Single () là "quyền" được sử dụng. Trong các tình huống khác, những người khác có thể thích hợp hơn. Trong các phiên bản trước của EF, chúng tôi đã giới hạn ở First () và FirstOrDefault () hoạt động cho các tình huống mà bạn đang mong đợi một bản ghi duy nhất nhưng chúng sẽ không cảnh báo bạn nếu bạn thực sự nhận được nhiều hơn bản ghi đó có thể quan trọng tùy thuộc vào tình huống.
Steve Willcock

1
Cảm ơn. Tôi không thể thấy mình cần First () nữa, trong đó Single () sẽ không tốt hơn. Nếu tôi bớt dày đặc hơn, tôi chắc chắn tôi có thể đánh giá cao / hiểu khi nào nên sử dụng First ().
asfsadf

1
First () có ý nghĩa nhất trong trường hợp bạn chỉ muốn truy xuất đối tượng có giá trị cao nhất hoặc thấp nhất trong số những gì bạn đang đặt hàng theo. Chẳng hạn, tìm cho tôi việc bán hàng với tổng giá trị cao nhất. Sales.OrderByDescending(s => s.TotalValue).First();
Mike Chamberlain

5
Tất cả các ý kiến ​​trên nhìn một sự khác biệt quan trọng. Find () là phương thức duy nhất tìm kiếm bối cảnh trước khi nhấn db.
Yaron Levi

5
Một điểm khác là khi truy vấn cơ sở dữ liệu sql, Singlehoặc SingleOrDefaultsẽ truy vấn 2 bản ghi (giới hạn 2) trong khi Firsthoặc FirstOrDefaultsẽ truy vấn cho 1 (giới hạn 1).
Bart Calixto

22

Tôi luôn có xu hướng sử dụng FirstOrDefault. Nếu bạn thực sự muốn kén chọn với hiệu suất thì bạn nên sử dụng FirstOrDefaulttrong EF. Trong các trang bìa SingleOrDefaultsử dụng top (2) trong truy vấn bởi vì, nó cần kiểm tra xem có hàng thứ hai phù hợp với tiêu chí hay không và nếu có, nó sẽ ném ra một ngoại lệ. Về cơ bản, SingleOrDefaultbạn đang nói rằng bạn muốn đưa ra một ngoại lệ nếu truy vấn của bạn trả về nhiều hơn 1 bản ghi.


5
Bạn đã bao giờ đo sự khác biệt hiệu suất giữa FirstOrDefaultSingleOrDefaultlà đáng kể? Tôi muốn nói rằng đó là tối ưu hóa sớm trong hầu hết các trường hợp.
Steven

Tôi có xu hướng sử dụng Single()hoặc SingleOrDefault()khi tôi trả lại một cái gì đó chỉ nên tồn tại một cái . Lý do tôi làm như vậy là để phát hiện ra các lỗi bằng cách thực hiện các truy vấn được viết xấu, trả về nhiều hơn mức cần thiết, thất bại. Ít nhất trong suy nghĩ của tôi, điều này sẽ giúp giữ cho dữ liệu trong hệ thống nhất quán. Tất nhiên điều này chậm hơn, nhưng tôi đoán rằng nó không chậm hơn nhiều, và tôi sẵn sàng trả giá đó.
mortb

15

Điều đó thực sự rất đơn giản: Singletrả về một mục duy nhất và ném ngoại lệ nếu không có hoặc có nhiều hơn một mục. Firstsẽ trả lại vật phẩm đầu tiên hoặc ném khi không có vật phẩm. FirstOrDefaultsẽ trả về mục đầu tiên hoặc trả về giá trị mặc định ( nulltrong trường hợp loại đã cho là loại tham chiếu) khi không có mục.

Đây là hành vi mà API được cho là có. Tuy nhiên, lưu ý rằng việc triển khai cơ bản có thể có một hành vi khác. Trong khi Entity Framework tuân theo điều này, một O / RM như LLBLGen cũng có thể quay lại nullkhi gọi Firstđó là một điều rất lạ. Đây là một quyết định rất kỳ lạ (và bướng bỉnh) của nhà thiết kế IMO.


Cảm ơn Steven. Tôi đoán tôi vẫn đang tự hỏi tại sao bạn lại sử dụng cái này? Tôi đã luôn sử dụng FirstOrDefault () và tò mò về lý do tại sao rất nhiều ví dụ mới mà tôi thấy đã chuyển sang Single (). Có một lý do để chuyển sang Single ()? Có những người khác cũng hoàn thành điều tương tự, mà tôi nên xem xét thay thế?
asfsadf

7
Nếu bạn muốn mã của mình "thất bại nhanh", Đầu tiên () và Độc thân () hãy để mã của bạn nói chính xác hơn những gì được mong đợi (vì vậy nó có thể thất bại theo cách khác)
Frank Schwieterman

3
Tôi hoàn toàn đồng ý với Frank. Đó cũng là về ý định truyền đạt. Singlebày tỏ rõ ràng rằng bạn chỉ mong đợi kết quả có một yếu tố.
Steven

8

Bốn phương pháp đều có vị trí của chúng; Mặc dù bạn thực sự chỉ có hai hoạt động khác nhau.

  • Đầu tiên - Mong đợi một tập kết quả có chứa nhiều mục, hãy cho tôi mục đầu tiên trong tập đó.
  • Độc thân - Mong đợi một kết quả duy nhất trở lại, đưa cho tôi mục đó.

Phiên bản xxxxOrDefault () chỉ thêm vào "Tôi không muốn coi một kết quả trống được đặt là một trường hợp đặc biệt."


OK, do đó, dường như với tôi rằng First () sẽ hiếm khi có ích. Tôi đang gặp khó khăn khi đưa ra một kịch bản trong đó Single () sẽ không phải là lựa chọn đầu tiên. Bạn có một tay nhanh chóng, tình cờ? Cảm ơn.
asfsadf

3
Thật không may, rất nhiều nhà phát triển sử dụng First () hoặc FirstOrDefault () hoàn toàn như một biện pháp phòng thủ, nghĩ rằng nó sẽ tránh được một ngoại lệ khi nó thực sự có khả năng che giấu các vấn đề thực sự.
Matt H

3

Mặt khác, bạn có thể chia các phương thức này theo logic cốt lõi, như thế này:

  • Phương thức sẽ truy vấn cơ sở dữ liệu trực tiếp : Single (), SingleOrDefault (), First (), FirstOrDefault ()
  • Phương thức sẽ thực hiện tìm kiếm trong bộ đệm trước khi đưa ra truy vấn đối với cơ sở dữ liệu : Find ()

Để biết một số chi tiết về hiệu suất, đặc biệt là trong trường hợp thứ hai, bạn có thể xem tại đây: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217394#3

Ngoài ra, trong nhóm đầu tiên, bạn có thể xác định các truy vấn phức tạp, nhưng với phương thức Find (), bạn chỉ có thể cung cấp khóa thực thể cho tìm kiếm.


0

Single ()SingleOrDefault () thường được sử dụng trên các số nhận dạng duy nhất như ID, trong khi First () hoặc FirstOrDefault () thường được sử dụng cho một truy vấn có thể có nhiều kết quả nhưng bạn chỉ muốn "Top 1" .

Single () hoặc First () sẽ đưa ra một ngoại lệ nếu không có kết quả nào được trả về, SingleOrDefault ()FirstOrDefault () bắt ngoại lệ và trả về null hoặc mặc định (resultDataType).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.