6

Tôi đăng bài này nhiều hơn vì tôi muốn tìm hiểu thêm, bởi vì công việc của tôi xung quanh đã cơ bản tránh sử dụng LINQ to Entities! Nó sẽ tốt đẹp nếu tôi có thể sử dụng nó mặc dù. Vì vậy, nếu có ai đó có thể khai sáng cho tôi ..LINQ to Entities ToString() - Không có giải pháp được đề xuất nào hoạt động?

Tôi đang làm việc trên ứng dụng ASP.Net MVC 3 (ứng dụng đầu tiên của tôi) bằng cách sử dụng Khuôn khổ thực thể mã đầu tiên làm mô hình dữ liệu của tôi. Nó sẽ là một cửa hàng trực tuyến và tôi đang làm việc trên bộ điều khiển 'Quản trị', với tư cách là quản trị viên, bạn có thể chỉnh sửa sản phẩm, v.v. Khi nói đến việc thêm sản phẩm mới, bạn phải chỉ định danh mục, có nghĩa là danh sách danh mục thả xuống.

Tôi bắt đầu bằng cách chỉ trả lại một bộ sưu tập danh mục IE có thể đếm được trong ViewBag, dựa trên thông tin tôi tìm thấy here. Điều này có vẻ giống như một cách thực sự tốt đẹp để tiếp cận mọi thứ.

Nhưng tôi gặp lỗi tương tự bạn sẽ thấy bên dưới. Vì vậy, sau một đề nghị tôi đọc trực tuyến, tôi đã tạo ra một mô hình riêng biệt đặc biệt để tạo mới và chỉnh sửa các sản phẩm hiện có. Bộ sưu tập Danh mục được sử dụng để tạo danh sách thả xuống trong chế độ xem.

public class ProductModel 
{ 
    public int Id { get; set; } 
    public int CategoryId { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public double Price { get; set; } 
    public bool IsVisible { get; set; } 

    public IEnumerable<SelectListItem> Categories 
    { 
     get 
     { 
      return new DataAccess() 
       .Categories 
       .OrderBy(c => c.Description) 
       .Select(c => new SelectListItem 
        { 
         Value = c.Id.ToString(), 
         Text = c.Description 
        }); 
     } 
    } 
} 

Điều này dẫn đến các thông báo lỗi sau: "LINQ to Entities không nhận ra phương pháp 'System.String ToString()' phương pháp, và phương pháp này không thể được dịch sang một biểu hiện cửa hàng.". Một giải pháp trực tuyến được đề xuất là sử dụng các phương thức SqlFunction được cung cấp bởi Entity Framework. Vì vậy, tôi đã cố gắng này để thay thế ...

public IEnumerable<SelectListItem> Categories 
    { 
     get 
     { 
      return new DataAccess() 
       .Categories 
       .OrderBy(c => c.Description) 
       .Select(c => new SelectListItem 
        { 
         Value = SqlFunctions.StringConvert((double)c.Id), 
         Text = c.Description 
        }); 
     } 
    } 

Nhưng kết quả này trong thông báo lỗi này: "Phương pháp xác định 'System.String StringConvert (System.Nullable`1 [System.Double])' vào loại ' System.Data.Objects.SqlClient.SqlFunctions 'không thể dịch thành biểu thức kho lưu trữ LINQ to Entities. ".

Tôi thậm chí đã thử thêm thuộc tính chỉ đọc vào lớp dữ liệu được gọi là IdAsString, nhưng điều này rõ ràng làm cho Khung thực thể rất không hài lòng!

Cuối cùng, tôi nhận ra rằng nó không xứng đáng với tất cả thời gian tôi đã đưa vào nó, và chỉ ngừng sử dụng LINQ hoàn toàn. Điều này làm việc tốt, nhưng nó sẽ được tốt đẹp để biết nếu có một "chính xác" cách để làm điều này mà thực sự hoạt động!

Đây là giải pháp làm việc hiện tại của tôi:

public IEnumerable<SelectListItem> Categories 
    { 
     get 
     { 
      var dal = new DataAccess(); 
      var categories = dal.Categories; 
      var items = new List<SelectListItem>(); 

      foreach (var category in categories) 
       items.Add(new SelectListItem 
        { 
         Value = category.Id.ToString(), 
         Text = category.Description 
        }); 

      return items; 
     } 
    } 

Vì vậy, nếu có ai đã làm điều này và họ nghĩ rằng họ đang làm việc đó "đúng" cách, sau đó tôi rất muốn biết những gì bạn nghĩ!

Trả lời

11

Thực hiện truy vấn trước khi bạn gọi ToString sẽ làm cho phần cuối cùng là truy vấn không phải thực thể. Bạn có thể tối ưu hóa điều này bằng cách chỉ chọn id và mô tả, sau đó gọi AsEnumerable, và sau đó nhận được selectlistitems.

return new DataAccess() 
     .Categories 
     .OrderBy(c => c.Description) 
     .AsEnumerable() 
     .Select(c => new SelectListItem 
      { 
       Value = c.Id.ToString(), 
       Text = c.Description 
      }); 
+0

Wow. Nó thực sự là đơn giản - cảm ơn bạn !! Tôi có cảm giác nó "nên" đơn giản! –

+3

Bạn cũng có thể sử dụng 'AsEnumerable' thay vì' ToList'. Phân bổ một danh sách mà sẽ chỉ được liệt kê là vô nghĩa. Với 'AsEnumerable' bạn sẽ liệt kê mỗi mục chỉ một lần, trái ngược với hai lần với' ToList'. Nếu bạn đang trả về một vài kết quả, sẽ không có bất kỳ sự khác biệt đáng kể nào. –

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