2010-12-15 29 views
11

Tôi có một truy vấn phương pháp như thế này:Tránh "Đối tượng dễ vỡ phải có giá trị." trong LINQ-to-SQL

public IList<BusinessObject> GetBusinessObject(Guid? filterId) 
{ 
    using (var db = new L2SDataContext()) 
    { 
     var result = from bo in db.BusinessObjects 
        where (filterId.HasValue) 
           ? bo.Filter == filterId.value 
           : true 
        orderby bo.Name 
        select SqlModelConverters.ConvertBusinessObject(bo); 
     return result.ToList(); 
    } 
} 

Khi chạy, điều này ném một System.InvalidOperationException: Nullable object must have a value.

Nhìn vào Debugger, vấn đề là tôi ở đâu khoản: LINQ to cố gắng SQL để chuyển đổi toàn bộ điều sang SQL, vì vậy ngay cả khi filterId là NULL, nó vẫn sẽ cố gắng truy cập filterId.value.

Tôi nghĩ/hy vọng trình biên dịch C#/CLR sẽ đánh giá rằng mệnh đề where là một khối mã và chỉ gửi một trong hai nhánh tới LINQ to SQL, nhưng đó không phải là cách nó hoạt động.

phiên bản refactored tôi làm việc, nhưng không phải là rất tao nhã:

public IList<BusinessObject> GetBusinessObject(Guid? filterId) 
{ 
    using (var db = new L2SDataContext()) 
    { 
     var temp = from bo in db.BusinessObjects select bo; 
     if(filterId.HasValue) temp = temp.Where(t => t.Filter == filterId.Value); 
     var result = from t in temp 
        orderby t.Name 
        select SqlModelConverters.ConvertBusinessObject(bo); 
     return result.ToList(); 
    } 
} 

Tôi biết rằng Lazy-đánh giá sẽ đảm bảo rằng chỉ có một truy vấn được thực sự được gửi, nhưng có đối tượng tạm thời trong đó không phải là thực sự tuyệt vời.

Trả lời

16

Bạn thử:

where filterId == null || t.Filter == filterId 
+1

Oh wow, làm việc một cách hoàn hảo! Nó tiết kiệm cho tôi từ việc sử dụng toán tử đại học không thể đọc được một chút, và nó giải quyết được ngoại lệ thực tế do việc truy cập filterId.Value không cần thiết thay vì chỉ là filterId. –

1

Sửa lỗi của bạn chính xác. Bạn đang cố gắng xây dựng một truy vấn một cách hiệu quả, dựa trên đầu vào hàm của bạn. Bạn nên bỏ qua mệnh đề where thay vì cung cấp WHERE TRUE. Nếu tôi đang viết truy vấn này, tôi sẽ tự mình làm phiên bản cố định của bạn.

Nó không đẹp bằng cách sử dụng từ khóa ngôn ngữ, nhưng đó vẫn là cách phù hợp để tiếp cận truy vấn theo ý kiến ​​của tôi.

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