2012-02-12 21 views
12

Tôi muốn tạo đối tượng mô hình mới có tên Movie_Type trong ứng dụng web ASP.NET MVC của tôi. Điều gì sẽ khác biệt nếu tôi xác định proprty điều hướng của lớp này là List, ICollection hoặc IQueryable như sau?Danh sách so với IEnumerable và IQueryable khi xác định Thuộc tính điều hướng

public partial class Movie_Type 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public List<Movie> Movies { get; set; } 
} 

HOẶC

public partial class Movie_Type 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public IQueryable<Movie> Movies { get; set; } 
} 

HOẶC

public partial class Movie_Type 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
    public ICollection<Movie> Movies { get; set; } 
} 

Chỉnh sửa: - @Tomas Petricek. cảm ơn câu trả lời của bạn. trong trường hợp của tôi, tôi đang sử dụng phương pháp tiếp cận cơ sở dữ liệu đầu tiên và sau đó tôi sử dụng mẫu DbContext để ánh xạ các bảng của tôi, được tự động tạo ra ICollection cho tất cả các thuộc tính điều hướng, Vì vậy, câu hỏi của tôi là: - 1. Điều này có nghĩa là không phải lúc nào cũng tốt nhất lựa chọn để sử dụng Icollection. Và tôi nên thay đổi các lớp được tạo tự động để phù hợp nhất với trường hợp của tôi. 2. Thứ hai tôi có thể quản lý để lựa chọn giữa tải lười biếng hoặc Háo hức bằng cách định nghĩa .include như

var courses = db.Courses.Include(c => c.Department); 

Bất kể những gì tôi đang sử dụng để xác định các tính chất điều hướng. Vì vậy, tôi không thể hiểu được điểm ur. 3. tôi không bao giờ tìm thấy bất kỳ ví dụ hoặc hướng dẫn sử dụng IQuerable để xác định các thuộc tính điều hướng ,, vì vậy những gì có thể là lý do? BR

+0

bạn đã thử điều này trước khi đăng bài ở đây phải không? – BrokenGlass

+1

http://stackoverflow.com/questions/3603545/ienumerablet-vs-ilistt-vs-iqueryablet bài đăng này sẽ giúp bạn quyết định – Devjosh

Trả lời

8

Có hai cách có thể nhìn sự vật:

  1. Là kết quả được lưu trữ trong bộ nhớ như là một phần của trường hợp đối tượng?
    Nếu bạn chọn ICollection, kết quả sẽ được lưu trữ trong bộ nhớ - điều này có thể không tốt nếu tập dữ liệu quá lớn hoặc nếu bạn không cần phải lấy dữ liệu. Mặt khác, khi bạn lưu trữ dữ liệu trong bộ nhớ, bạn sẽ có thể sửa đổi tập dữ liệu từ chương trình của mình.

  2. Bạn có thể tinh chỉnh truy vấn được gửi đến máy chủ SQL không?
    Điều này có nghĩa là bạn có thể sử dụng LINQ trên thuộc tính trả về và các toán tử LINQ bổ sung sẽ được dịch sang SQL - nếu bạn không chọn tùy chọn này, việc xử lý LINQ bổ sung sẽ chạy trong bộ nhớ.

Nếu bạn muốn lưu trữ dữ liệu trong bộ nhớ, bạn có thể sử dụng ICollection. Nếu bạn muốn có thể tinh chỉnh truy vấn, thì bạn cần sử dụng IQueryable. Dưới đây là bảng tóm tắt:

|     | Refine query | Don't change query | 
|-----------------|--------------|--------------------| 
| In-memory  | N/A  | ICollection  | 
| Lazy execution | IQueryable | IEnumerable  | 
+2

+1 - thật tuyệt vời khi một bức tranh (nếu đó là những gì bạn có thể gọi là biểu đồ của bạn) có giá trị 1000 từ. Tôi chỉ có bóng đèn bật sự kiện :) – Jesse

+0

cảm ơn trả lời ur, xem chỉnh sửa của tôi. BR –

+4

Bạn không thể sử dụng 'IQueryable 'cho thuộc tính điều hướng. – Slauma

0

Tiêu chuẩn khác là IE có thể đếm được vì nó là mẫu số chung ít nhất.

Tôi có thể trả về nếu bạn muốn thêm chức năng truy vấn cho người gọi mà không có 10 phương thức lưu trữ để xử lý các kịch bản truy vấn khác nhau.

Một nhược điểm là ienumerable có thể 'đếm()' chậm nhưng nếu đối tượng thực hiện ICollection thì giao diện này được kiểm tra cho giá trị này trước mà không phải liệt kê tất cả các mục.

Cũng lưu ý nếu bạn quay lại IQueryable để một người gọi không tin cậy họ có thể làm một số đúc và phương pháp kêu gọi IQueryable và được tiếp cận với bối cảnh, kết nối, chuỗi kết nối, truy vấn chạy, vv

Cũng lưu ý nhibernate cho ví dụ có một đối tượng truy vấn bạn có thể chuyển đến một kho lưu trữ để chỉ định các tùy chọn. Với khung thực thể, bạn cần trả lại IQueryable để nâng cao tiêu chí truy vấn

+0

cảm ơn trả lời của bạn, hãy xem bài chỉnh sửa của tôi. BR –

14

Bạn không thể sử dụng thuộc tính điều hướng thuộc loại IQueryable<T>. Bạn phải sử dụng ICollection<T> hoặc một số loại bộ sưu tập thực hiện ICollection<T> - như List<T>. (IQueryable<T> không triển khai ICollection<T>.)

Thuộc tính điều hướng chỉ đơn giản là đối tượng hoặc tập hợp các đối tượng trong bộ nhớ hoặc là null hoặc bộ sưu tập trống.

Nó không bao giờ được nạp từ cơ sở dữ liệu khi bạn tải đối tượng mẹ chứa thuộc tính điều hướng từ cơ sở dữ liệu.

Bạn có thể phải explicitely nói rằng bạn muốn tải các tài sản chuyển hướng cùng với phụ huynh đó là háo hức tải:

var movieTypes = context.Movie_Types.Include(m => m.Movies).ToList(); 
// no option to filter or sort the movies collection here. 
// It will always load the full collection into memory 

Hoặc nó sẽ được nạp bởi lười tải (được kích hoạt theo mặc định nếu bất động sản chuyển hướng của bạn là virtual):

var movieTypes = context.Movie_Types.ToList(); 
foreach (var mt in movieTypes) 
{ 
    // one new database query as soon as you access properties of mt.Movies 
    foreach (var m in mt.Movies) 
    { 
     Console.WriteLine(m.Title); 
    } 
} 

tùy chọn cuối cùng là tải rõ ràng mà xuất phát gần nhất với ý định của bạn tôi đoán:

var movieTypes = context.Movie_Types.ToList(); 
foreach (var mt in movieTypes) 
{ 
    IQueryable<Movie> mq = context.Entry(mt).Collection(m => m.Movies).Query(); 
    // You can use this IQueryable now to apply more filters 
    // to the collection or sorting, for example: 
    mq.Where(m => m.Title.StartWith("A")) // filter by title 
     .OrderBy(m => m.PublishDate)   // sort by date 
     .Take(10)        // take only the first ten of result 
     .Load();        // populate now the nav. property 
    // again this was a database query 

    foreach (var m in mt.Movies) // contains only the filtered movies now 
    { 
     Console.WriteLine(m.Title); 
    } 
} 
+2

đó là một sự xấu hổ, bởi vì nó có nghĩa là bạn phải vượt qua bối cảnh xung quanh tất cả các nơi, chỉ để làm các truy vấn phụ hiệu quả thay vì điều hướng ngây thơ. – Spongman

0

Các bộ sưu tập mà khuôn khổ thực thể thực sự tạo ra cho bạn nếu bạn sử dụng tài sản chuyển hướng ảo thực hiện ICollection, nhưng không IQueryable, vì vậy bạn không thể sử dụng IQueryable đối với tài sản chuyển hướng của bạn, như Slauma nói.

Bạn được tự do xác định thuộc tính của mình là IEnumerable, vì ICollection mở rộng IEnumerable, nhưng nếu bạn làm điều này thì bạn sẽ mất khả năng thêm các mục con mới vào các thuộc tính điều hướng này.

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