2009-09-18 43 views
6

Tôi đang sử dụng Thư viện LINQ động/Mẫu từ Microsoft để đặt hàng trên danh sách. Vì vậy, ví dụ tôi có mã C# sau:Ngoại lệ tham chiếu Null trong biểu thức LINQ động

myGrid.DataSource=repository.GetWidgetList() 
     .OrderBy(sortField + " " + sortDirection).ToList(); 

Tôi có trường hợp đối tượng của tôi có mối quan hệ 0: 1 với một đối tượng có thể được hiển thị trong lưới. Khi chúng tôi cố gắng và sắp xếp điều này, nó hoạt động tốt miễn là tất cả các Widget của tôi có con này. Chúng tôi đang đặt hàng theo số Child.Name chẳng hạn. Tuy nhiên, khi Child là null, chúng ta nhận được ngoại lệ tham chiếu null.

Tôi có một số tùy chọn ở đây mà tôi biết tôi có thể chọn vào loại ẩn danh và liên kết với điều đó, tôi cũng có thể hiển thị Child.Name trên đối tượng mẹ và xử lý mã này (Tôi không thích bao gồm mô hình đối tượng cho điều này).

Trong một thế giới lý tưởng, tôi muốn cập nhật thư viện để xử lý trường hợp này. Trước khi tôi đi sâu vào nó, tôi tự hỏi nếu có ai đã chạy qua này hay không và đã có một giải pháp chưa?

Sửa

Hình như tôi đã không giải thích cũng đủ. Tôi đang sử dụng số Dynamic Linq Library đi kèm với C# samples. Thư viện này cho biết thêm một số phần mở rộng thoải mái cho phép bạn sử dụng một chuỗi inplace của một biểu thức lambda Vì vậy, mã của tôi thực sự là một cái gì đó như thế này:

private void BindGrid(sortField,sortDirection) 
{ 

    this.grid.DataSource=....OrderBy("MyField ASC").... 
} 

Tất nhiên chuỗi có được thay thế bằng các thông số. Nhưng điều này cho phép chúng tôi thay đổi sắp xếp động khi người dùng nhấp vào tiêu đề lưới. Chúng ta không phải làm gì nếu logic khác xử lý tất cả các hoán vị.

Giải pháp của tôi như tôi ghi nhận dưới đây thay đổi thoải mái phương pháp sạch của tôi vào:

private void BindGrid() 
{ 
    var sortField=this._sortField; 
    if (sortField=="Child.Name") 
    { 
     sortField="iif(Child==null,null,Child.Name)"; 
    } 
    this.grid.DataSource=repository.GetWidgetList() 
            .OrderBy(sortField + " " + this._sortDirection) 
            .ToList(); 
} 

Và trong khi các công trình này, điều này bây giờ có nghĩa là tôi phải cập nhật mã này như chúng ta thêm lĩnh vực mới hoặc tài sản mà chúng tôi muốn để lộ trong lưới nằm trên đối tượng con.

Trả lời

5

Nếu tôi hiểu bạn một cách chính xác, tôi nghĩ rằng bạn muốn điều này:

repository.GetParentObjects() 
    .OrderBy(p => p.Child == null ? "" : p.Child.Name); 

LINQ sẽ có thể tạo ra SQL bắt chước biểu thức này.

+1

Không phải đây là điều tôi đang đề cập đến. LINQ động là một phần của mã mẫu C# và cho phép bạn sử dụng một chuỗi như một OrderBy chẳng hạn. Nó biên dịch chuỗi thành một biểu thức lambda trong thời gian chạy. – JoshBerke

+6

Tại sao câu trả lời này được chấp nhận là câu trả lời thực tế? Tôi đang ở trong tình trạng tương tự. – Mike

2

On giải pháp tôi đã tìm thấy mà trong trường hợp của tôi không phải là lý tưởng một lần nữa sẽ được phát hiện khi biểu thức sẽ truy cập vào đứa trẻ, để thay đổi biểu hiện sắp xếp để được

iif(Child == null,null,Child.Name) ASC 

Lý tưởng nhất là logic này có thể được nướng vào thư viện năng động, tôi không muốn phải sửa đổi mỗi lưới trên tất cả các nơi để xử lý tất cả các trường hợp này sẽ tác động.

-2

Tôi không thực sự hiểu vấn đề (có thể vì nó là buổi tối thứ sáu ở đây đã ...), nhưng bạn không thể sắp xếp danh sách như thế này:

myGrid.DataSource=repository.GetWidgetList() 
    .OrderBy(w => w.SortField).ToList(); 

nơi SortField là tài sản bạn muốn sắp xếp. này nên làm việc ngay cả khi giá trị là null ...

Xin lỗi nếu nó có thể hoàn toàn bên cạnh điểm ...

+2

Bạn đã hoàn toàn bỏ lỡ điểm. Vì bạn không phải là người duy nhất tôi phải không giải thích cho bản thân mình đủ tốt. Tôi đã cập nhật câu hỏi để nó có thể là một chút nhưng rõ ràng hơn. – JoshBerke

1

tôi đã cùng một vấn đề nhưng giải pháp tốt nhất mà tôi tìm thấy là làm cho mã của bạn một chút chung chung hơn bằng cách thay đổi nó vào đây:

private void BindGrid() 
{ 
    var sortField = this._sortField; 
    var splitted_sortField = this._sortField.Split(new char[]{'.'}, StringSplitOptions.RemoveEmptyEntries); 
    if (splitted_sortField.Length > 1) 
    { 
     sortField = "iif("+splitted_sortField[0]+"==null,null,"+sortField+")"; 
    } 
    this.grid.DataSource = repository.GetWidgetList() 
            .OrderBy(sortField + " " + this._sortDirection) 
            .ToList(); 
} 

Không hoàn hảo, sẽ không giống như cung cấp cho truy cập vào Childs của Childs , nhưng tiết kiệm u từ việc cập nhật mã của bạn mỗi khi bạn nhận được một con nullable mới.

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