2008-10-02 42 views
5

Tôi đang gặp phải một số điểm khác biệt với LINQ to SQL.Các đặc tính LINQ to SQL

Với một truy vấn tương đối đơn giản, tôi muốn chọn một số lĩnh vực, nhưng có trường ngày định dạng như dây đàn, mà tôi lần đầu tiên đạt được như thế này:

 var list = dataContext.MyLists.Single(x => x.ID == myId); 

     var items = from i in list.MyItems 
        select 
         new 
          { 
           i.ID, 
           i.Sector, 
           i.Description, 
           CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "", 
           DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : "" 
          };        

Sau đó tôi đã cố gắng truy vấn sau, đó là giống hệt nhau, ngoại trừ tôi truy vấn trực tiếp từ DataContext của tôi, chứ không phải là một yếu tố trong truy vấn đầu tiên của tôi:

 var items = from i in dataContext.MyLists 
        select 
         new 
          { 
           i.ID, 
           i.Sector, 
           i.Description, 
           CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "", 
           DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : "" 
          }; 

người đầu tiên chạy tốt, nhưng các truy vấn thứ hai mang lại một:

Không thể dịch biểu thức '...' thành SQL và không thể xử lý biểu thức dưới dạng biểu thức cục bộ.

Nếu tôi xóa các dòng Định dạng ngày, nó hoạt động tốt. Nếu tôi loại bỏ .HasValue kiểm tra xem nó cũng hoạt động tốt, cho đến khi có giá trị null.

Bất kỳ ý tưởng nào?

Anthony

+0

Có vẻ bạn có hai câu hỏi hoàn toàn khác nhau. Một là chọn từ MyItems trong một đối tượng MyList. Thứ hai là chọn từ các đối tượng MyList (không phải MyItems). Các kiểu dữ liệu có giống nhau không? Nó là khá khó khăn để gỡ lỗi này mà không biết những gì các cấu trúc bảng được. – Bryant

Trả lời

14

tôi sẽ làm phần SQL mà không làm các định dạng, sau đó làm các định dạng trên các mặt hàng:

var items = list.MyItems.Select(item => new { item.ID, item.Sector, item.Description, 
               item.CompleteDate, item.DueDate }) 
         .AsEnumerable() // Don't do the next bit in the DB 
         .Select(item => new { item.ID, item.Sector, item.Description, 
               CompleteDate = FormatDate(CompleteDate), 
               DueDate = FormatDate(DueDate) }); 


static string FormatDate(DateTime? date) 
{ 
    return date.HasValue ? date.Value.ToShortDateString() : "" 
} 
+0

Ooooh Tôi thích điều đó .AsEnumerable() tách ra ở đó. Tốt đẹp. – Lucas

+0

Lưu bởi SO một lần nữa ... cảm ơn !! –

+0

@Jon Skeet - Tôi yêu bạn. –

8

Trong truy vấn đầu tiên, bạn đã nhận được dữ liệu trở lại từ cơ sở dữ liệu vào thời điểm dòng thứ hai chạy (var mục = ...). Điều này có nghĩa là dòng thứ 2 chạy ở máy khách, nơi ToShortDateString có thể chạy khá vui vẻ.

Trong truy vấn thứ hai, vì chọn chạy trực tiếp trên một bộ sưu tập IQueryable (dataContext.MyLists), nó cố gắng dịch chọn SQL thành xử lý tại máy chủ, nơi ToShortDateString không được hiểu - do đó "Không thể dịch .." ngoại lệ.

Để hiểu điều này tốt hơn một chút, bạn thực sự cần phải hiểu sự khác biệt giữa IQueryable và IEnumerable, và tại thời điểm đó truy vấn LINQ to Sql dừng lại là IQueryable và trở thành IEnumerable. Có rất nhiều thứ trên web về điều này.

Hope this helps,

Paul

6

Cũng giống như các thông báo lỗi cho bạn biết, sự khác biệt là do những gì có thể được thực hiện tại địa phương từ xa trong khi kết nối với SQL.

Mã LINQ phải được chuyển đổi bởi LINQ thành SQL thành lệnh SQL để lấy dữ liệu từ xa - mọi thứ phải được thực hiện cục bộ không thể được bao gồm.

Khi bạn đã kéo nó vào một đối tượng cục bộ (trong ví dụ đầu tiên), nó không sử dụng LINQ to SQL nữa, chỉ đơn giản là LINQ. Tại thời điểm đó, bạn được tự do thực hiện các thao tác cục bộ trên đó.

2

Có thể có lỗi sao chép và dán hoặc chỉ là lỗi đánh máy trong mẫu của bạn. Nhưng nếu không, đây có thể là sự cố ...

Trong truy vấn thứ hai bạn đang truy vấn một tập hợp danh sách, trong khi truy vấn đầu tiên bạn đang truy vấn các mục trong danh sách. Nhưng bạn chưa điều chỉnh truy vấn để giải thích sự khác biệt này.

Điều bạn cần có thể là điều này. Lưu ý các dòng nhận xét không xuất hiện trong mẫu thứ hai của bạn.

var items = from aList in dataContext.MyLists 
       from i in aList.MyItems // Access the items in a list 
       where aList.ID == myId // Use only the single desired list 
       select 
        new 
         { 
          i.ID, 
          i.Sector, 
          i.Description, 
          CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "", 
          DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : "" 
         };