2010-01-26 20 views
7

Để có được một danh sách các hồ sơ Tôi thường làm điều gì đó dọc theo dòng:Entity Framework - Cách thực hiện để kiểm tra hồ sơ duy nhất trước khi sử dụng chúng

var efCompany = from a in _dbRiv.Company where a.CompanyId == companyFeedInfo.CompanyId select a; 

Để có được một hồ sơ duy nhất, khi tôi biết tôi đang sử dụng PK để lấy nó, tôi sử dụng cái gì đó như:

var efCompany = (from a in _dbRiv.Company where a.CompanyId == companyFeedInfo.CompanyId select a).First(); 

Bây giờ, sử dụng phương pháp hồ sơ duy nhất, nếu PK là một giá trị bị lỗi (như nó cố tình là trong thử nghiệm) dòng thứ 2 ném một lỗi.

thực hành tốt nhất cách nhận một bản ghi duy nhất và xử lý nó là gì?

Trả lời

18

Sử dụng SingleOrDefault nếu bạn mong đợi 0 hoặc 1 hoặc FirstOrDefault nếu bạn chỉ cần bản ghi đầu tiên có thể nhiều, nhưng có thể đối phó với 0. Cả hai sẽ trả về giá trị mặc định cho loại (thường là null) nếu không có các kết quả.

Bằng cách này, các truy vấn như thế này là tổng quát hơn có thể đọc được (IMO) mà không sử dụng một biểu thức truy vấn, vì vậy bạn có thể có một cái gì đó như:

var efCompany = _dbRiv.Company 
         .Where(a => a.CompanyId == companyFeedInfo.CompanyId) 
         .SingleOrDefault(); 

if (efCompany != null) 
{ 
    // Use it 
} 
else 
{ 
    // Report to user, or whatever 
} 

biểu thức truy vấn là tuyệt vời khi bạn đang sử dụng nhiều nhà khai thác hoặc thực hiện những việc tương đối phức tạp như tham gia - nhưng nếu bạn đã chỉ cần có điều khoản where hoặc chỉ được chiếu, "ký hiệu chấm" này là IMO đơn giản hơn. Nó cũng hoạt động tốt hơn khi bạn cần gọi một phương thức như FirstOrDefault ở cuối.

+0

Cảm ơn nhận xét bổ sung về biểu thức truy vấn. Vẫn học được rất nhiều về EF và tâm trí của tôi không hoàn toàn quấn quanh cú pháp lambda. Nhắc tôi rất nhiều con trỏ bộ nhớ C cũ. ;) –

+3

'SingleOrDefault' được hỗ trợ trong EF 4, nhưng không phải trong EF 1.' FirstOrDefault' được hỗ trợ cả hai. –

+0

@Jon Skeet - Whats sự khác biệt giữa việc đặt các từ khóa đặt hàng trên chuỗi LINQ ... ví dụ: '_db.MyModels.Where (a => a.Prop ==" value "). SingleOrDefault();' so với '_db.MyModels.SingleOrDefault(). ở đâu (a => a.Prop ==" giá trị "); '- Biểu diễn? Lệnh thi hành? vv ... –

7

Lưu ý rằng cả hai SingleOrDefault()FirstOrDefault() sẽ không cho phép bạn chỉ định giá trị mặc định.

DefaultIfEmpty(), cho phép bạn chỉ định giá trị mặc định bạn muốn trả lại nếu không có mục nào trong số đếm được. Bạn có thể kết hợp cái này với First() (như trong DefaultIfEmpty().First()) để đạt được FirstOrDefault() hành vi giống như và một lambda để bọc tạo một thể hiện mới và thêm nó vào bộ này.

Nếu bạn chỉ cần kiểm tra sự tồn tại của một bản ghi, bạn cũng có thể sử dụng Any(). Tuy nhiên, điều này sẽ dẫn đến hai truy vấn, nếu bạn cần xử lý bản ghi nếu nó tồn tại.

+0

Bất kỳ() là cách tốt nhất để đi nếu bạn chỉ cần kiểm tra sự tồn tại. –

+0

'DefaultIfEmpty', như' SingleOrDefault', được hỗ trợ trong EF 4 nhưng không được EF 1. –

+0

Tôi biết điều này là 8 tuổi nhưng cơ hội của một ví dụ? – Cloud

1
var efCompany = _dbRiv.Company 
        .SingleOrDefault(a => a.CompanyId == companyFeedInfo.CompanyId); 

if (efCompany != null) 
{ 
    // Use it 
} 
else 
{ 
    // Report to user, or whatever 
} 
0

Bạn cũng có thể sử dụng

_dbRiv.Company.find(#id) 

nếu bạn đang tìm kiếm một kỷ lục mà không cần mô hình bao gồm nó.

Hoặc

_dbRiv.Company.FirstOrDefault(x => x.Id == #id); 

Tôi khuyên bạn nên FirstOrDefault qua SingleOrDefault vì hiệu suất. Với SingleOrDefault, nó cần quét toàn bộ bảng và đảm bảo chỉ có một bản ghi có Id. Với FirstOrDefault nó chỉ đơn giản là có thể đi cho đến khi nó tìm thấy id đó rồi dừng lại. Trên một bảng lớn, nó sẽ giúp bạn tiết kiệm một lượng nhỏ thời gian với mỗi truy vấn.

Ngoài ra, bạn có thể sử dụng AsNoTracking để cải thiện mức tiêu thụ bộ nhớ nếu bạn không cần theo dõi bất kỳ thay đổi nào được thực hiện cho mô hình.Ví dụ: nếu bạn trả lại thông qua yêu cầu còn lại mà không cần gọi lưu.

+0

Tôi đoán vậy nó nếu có một chỉ mục nó sẽ không cần phải quét toàn bộ bảng. –

Các vấn đề liên quan