2015-09-08 17 views
16

Lớp ẩn danh chỉ đọc thuộc tính trong C#. Thường được sử dụng để khai báo trong truy vấn chọn LINQ để nhận các giá trị cụ thể từ cơ sở dữ liệu. Trong mã của tôi, tôi có truy vấn sau đây. Điều làm tôi bối rối khi chọn đối tượng mới của lớp ẩn danh bằng cách sử dụng câu lệnh mới. Tôi có một lớp mô hình là StudentClerkshipsLogModel. Khi tôi sử dụng tên model, kết quả truy vấn cho phép chỉnh sửa.LINQ chọn truy vấn có loại Chưa xác định và người dùng Kiểu xác định

var query = (from entity in _tblStudentClerkshipsLog.GetQueryable() 
      where entity.StudentID == intStudentID        
      select new StudentClerkshipsLogModel 
      { 
       StudentClerkshipID = entity.StudentClerkshipID, 
       StudentID = entity.StudentID, 
       ClerkshipID = entity.ClerkshipID, 
      }).ToList(); 

Khi tôi không đề cập đến loại sau new trong select tuyên bố tôi không thể thoát ra. trình biên dịch tăng lỗi. đối tượng đồng nghĩa chỉ đọc.

var query = (from entity in _tblStudentClerkshipsLog.GetQueryable() 
      where entity.StudentID == intStudentID        
      select new 
      { 
       StudentClerkshipID = entity.StudentClerkshipID, 
       StudentID = entity.StudentID, 
       ClerkshipID = entity.ClerkshipID, 
      }).ToList() 

câu hỏi của tôi là cách linq liên kết với hai truy vấn khác nhau. Cả hai truy vấn có liên kết động hoặc đầu tiên là tĩnh.

Cảm ơn

+3

Ý của bạn là gì bởi "Tôi không thể thoát"? Mã trình biên dịch phàn nàn là gì? (Tôi nghi ngờ rằng đó là mã bạn đã hiển thị.) Bạn có đang cố chỉnh sửa các đối tượng sau này không? Nếu có, hãy hiển thị mã. –

+0

tôi muốn sửa đổi mã sau. Nhưng tôi cần phải biết sự khác biệt giữa các truy vấn chọn để tôi có thể lựa chọn tốt hơn. –

+1

@JonSkeet: nó trông giống như một lỗi đánh máy. "Tôi không thể * chỉnh sửa *". – Dennis

Trả lời

11

Nếu tôi hiểu bạn một cách chính xác, bạn đang tự hỏi, làm thế nào nhà cung cấp LINQ có thể thiết lập các thuộc tính của đối tượng ẩn danh, vì chúng là "true" chỉ đọc tài sản (không có bất kỳ private set, nhưng get chỉ) ?

Khi bạn gọi Select phương thức mở rộng cho IQueryable<T>, nó chấp nhận biểu thức loại Expression<Func<T, TResult>. Nếu bạn sẽ viết một số stub cho Select bạn có thể nhìn vào biểu thức tạo ra, sử dụng trình gỡ lỗi:

public static class MyExtensions 
{ 
    public static void MySelect<T, TResult>(this IQueryable<T> query, Expression<Func<T, TResult>> projection) 
    { 
     System.Diagnostics.Debug.WriteLine(projection); 
    } 
} 

Sự khác biệt là ở cách biên dịch tạo ra các biểu thức lambda với nhiều loại tên và các loại vô danh. Khi bạn gọi Select cho loại tên, biểu hiện sẽ trông như thế này:

{_ => new Person() {Id = _.Id, Name = _.Name}} 

Đó là, đối tượng đầu tiên mới Person sẽ được xây dựng, và sau đó các thành viên sẽ được khởi tạo (MemberInit expression).

Nhưng khi bạn gọi Select cho loại hình mang tính chất biểu hiện sẽ được xây dựng như cuộc gọi constructor (New expression):

{_ => new <>f__AnonymousType0`2(a = _.Id, b = _.Name)} 

nhà cung cấp LINQ biên dịch những lambdas vào các đại biểu, khi vật chất hóa kết quả truy vấn, và cuối cùng chỉ gọi constructor cho loại ẩn danh.

17

Các lỗi mà bạn đang nhận được thực sự không có bất cứ điều gì để làm với LINQ. Bạn có thể thấy điều tương tự mà không sử dụng LINQ tại tất cả:

var anonymous = new { Name = "Fred" }; 
anonymous.Name = "Joe"; // Error, as properties of anonymous types are read-only 

Vì vậy, nếu bạn muốn thay đổi các đối tượng lấy bằng truy vấn LINQ của bạn, bạn không nên sử dụng các loại vô danh. Nhưng cả hai truy vấn LINQ đều bị ràng buộc tĩnh - các kiểu vô danh vẫn được biết đầy đủ tại thời gian biên dịch, và trình biên dịch áp dụng các hạn chế kiểu bình thường cho chúng. Ví dụ:

var anonymous = new { Name = "Fred" }; 
Console.WriteLine(anonymous.Foo); // Error: no property Foo 
int bar = anonymous.Name; // Error: no conversion from string to int 
+0

tôi biết điều này nhưng điều tôi muốn biết cách xử lý LINQ sau đó bởi vì các truy vấn hoạt động hoàn toàn khác nhau. tôi đã đề cập đến trong câu hỏi rằng đối tượng ẩn danh chỉ đọc –

2

Tôi tìm thấy sự khác biệt sau với kết quả loại ẩn danh của kết quả LINQ.

  1. Kết quả không thể chỉnh sửa, ví dụ:nếu chúng tôi chỉ định giá trị cho lưới ảnh, thì sẽ chỉ đọc.

  2. Vấn đề với phạm vi của một đối tượng ẩn danh.chúng tôi không thể chuyển loại sang phương thức khác. định nghĩa một tham số của kiểu var; var phải luôn luôn được theo sau bởi một biểu thức khởi tạo.

Nếu bạn chỉ cần kết quả trong ngữ cảnh hiện tại cho mục đích chỉ đọc sử dụng truy vấn ẩn danh. Nếu bạn cần kết quả trong chức năng khác, bạn phải xác định loại đối tượng. loại đối tượng sau new sẽ được tạo với thuộc tính bạn muốn nhận được từ kết quả xác định sau đó trong dấu ngoặc nhọn {}. Không cần thiết phải khởi tạo tất cả giá trị của lớp mô hình.

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