Tôi gặp sự cố khi xây dựng truy vấn LINQ của khung thực thể có mệnh đề chọn chứa các cuộc gọi phương thức tới các đối tượng không phải EF.Điều khoản chọn có chứa các cuộc gọi phương thức không phải EF
Mã bên dưới là một phần của ứng dụng được sử dụng để chuyển đổi dữ liệu từ một DBMS thành một giản đồ khác trên một DBMS khác. Trong đoạn mã dưới đây, vai trò là lớp tùy chỉnh của tôi không liên quan đến các DBMS, và các lớp khác đều được tạo ra bởi Entity Framework từ giản đồ DB của tôi:
// set up ObjectContext's for Old and new DB schemas
var New = new NewModel.NewEntities();
var Old = new OldModel.OldEntities();
// cache all Role names and IDs in the new-schema roles table into a dictionary
var newRoles = New.roles.ToDictionary(row => row.rolename, row => row.roleid);
// create a list or Role objects where Name is name in the old DB, while
// ID is the ID corresponding to that name in the new DB
var roles = from rl in Old.userrolelinks
join r in Old.roles on rl.RoleID equals r.RoleID
where rl.UserID == userId
select new Role { Name = r.RoleName, ID = newRoles[r.RoleName] };
var list = roles.ToList();
Nhưng gọi ToList mang lại cho tôi NotSupportedException này:
LINQ to Entities không nhận phương pháp 'Int32 get_Item (System.String)' phương pháp, và phương pháp này không thể được dịch ra tiếng một biểu hiện cửa hàng
Các âm thanh như LINQ-to-Entities đang chặn trên cuộc gọi của tôi để kéo giá trị ra khỏi từ điển được đặt làm tên khóa. Tôi thừa nhận là không hiểu đủ về EF để biết tại sao đây lại là một vấn đề.
Tôi đang sử dụng nhà cung cấp khung thực thể dotConnect for PostgreSQL của devart, mặc dù tôi giả định vào thời điểm này rằng đây không phải là vấn đề cụ thể về DBMS.
Tôi biết tôi có thể làm cho nó hoạt động bằng cách chia tay truy vấn của tôi vào hai truy vấn, như thế này:
var roles = from rl in Old.userrolelinks
join r in Old.roles on rl.RoleID equals r.RoleID
where rl.UserID == userId
select r;
var roles2 = from r in roles.AsEnumerable()
select new Role { Name = r.RoleName, ID = newRoles[r.RoleName] };
var list = roles2.ToList();
Nhưng tôi đã tự hỏi nếu có một cách thanh lịch hơn và/hoặc hiệu quả hơn để giải quyết vấn đề này , lý tưởng mà không chia nó thành hai truy vấn.
Dù sao, câu hỏi của tôi là hai phần:
Trước tiên, tôi có thể chuyển đổi truy vấn LINQ này thành một cái gì đó Entity Framework sẽ chấp nhận, lý tưởng mà không cần tách thành hai mảnh?
Thứ hai, tôi cũng muốn hiểu một chút về EF vì vậy tôi có thể hiểu lý do tại sao EF không thể lớp mã .NET tùy chỉnh của tôi trên đầu trang của truy cập DB. DBMS của tôi không có ý tưởng làm thế nào để gọi một phương thức trên một lớp học từ điển, nhưng tại sao không thể EF chỉ đơn giản là thực hiện các cuộc gọi phương thức từ điển sau khi nó đã được kéo dữ liệu từ DB? Chắc chắn, nếu tôi muốn soạn nhiều truy vấn EF cùng nhau và đặt mã .NET tùy chỉnh ở giữa, tôi mong đợi điều đó sẽ thất bại, nhưng trong trường hợp này mã .NET chỉ ở cuối, vậy tại sao đây lại là vấn đề EF? Tôi cho rằng câu trả lời là một cái gì đó như "tính năng đó không biến nó thành EF 1.0" nhưng tôi đang tìm kiếm một chút giải thích thêm về lý do tại sao điều này là khó đủ để biện minh cho việc rời khỏi EF 1.0.
Có vẻ như tôi đã đánh giá cao tính thông minh của LINQ đối với thực thể. Tôi đã giả định rằng L-to-E đủ thông minh để phân hủy một cây biểu thức thành phần mà DB có thể xử lý, và một phần khác mà nó phải giải quyết bằng cách sử dụng các cuộc gọi .NET (bên ngoài DB), và sau đó ghép hai cùng với nhau. Nếu tôi hiểu bạn một cách chính xác, bạn đang nói rằng L-to-E không phải là thông minh-- rằng nó chỉ đơn giản cố chuyển đổi mọi thứ * trong biểu thức thành SQL, và nếu có thứ gì đó không thể biến đổi (ví dụ: gọi một phương thức đối tượng .NET trong mệnh đề select), sau đó nó sẽ không thực hiện được? –
Đúng vậy, Justin. Lưu ý: Tự động phân tách truy vấn trên các tầng, là 'truy vấn được phân phối', một vấn đề cực kỳ khó giải quyết chung. –
Phải. LINQ to Entities giữ tất cả mọi thứ như một cây biểu thức mà cuối cùng nó sẽ sử dụng đối với cơ sở dữ liệu chỉ khi nó được * thực sự * lặp lại. Đó là "ngu ngốc" theo cách đó, nhưng đó là bởi vì, như Alex nói, truy vấn phân tán là một vấn đề cực kỳ khó giải quyết khi mọi thứ trở nên phức tạp hơn một chút. Tuy nhiên, hãy biết rằng bạn có thể sử dụng phép lặp làm dấu trang để kéo dữ liệu đến máy khách. –