2013-04-27 19 views
5

Hi i có mã sau đây để chọn dữ liệu từ một bảng không có trong bảng khácLINQ để chọn dữ liệu từ một bảng không có trong bảng khác

var result1 = (from e in db.Users 
       select e).ToList(); 
var result2 = (from e in db.Fi 
       select e).ToList(); 
List<string> listString = (from e in result1 
          where !(from m in result2 
            select m.UserID).Contains(e.UserID) 
          select e.UserName).ToList(); 

ViewBag.ddlUserId = listString; 

Am nhận được giá trị bên trong listString .Nhưng có lỗi khi thêm listString để xem túi.

Unable to cast object of type 'System.Collections.Generic.List`1[System.String]' to type 'System.Collections.Generic.IEnumerable`1[Main.Models.Admin.User]'. 
+0

Kiểm tra kiểu dữ liệu của 'ddlUserId', có thể không khớp với chuỗi! – zey

+0

Có vẻ như ViewBag.ddlUserId đang mong đợi một đối tượng người dùng IEnumerable.nhưng kết quả của truy vấn là danh sách các chuỗi –

+0

Tôi nghĩ rằng Người dùng quản trị là một enum. – Amit

Trả lời

15

Trước tiên, bạn có thể cập nhật câu hỏi của mình với toàn bộ phương pháp để chúng tôi có thể xem điều gì có thể xảy ra với ViewBag không? Vì mã của bạn nên hoạt động tốt, việc gán bất kỳ giá trị nào cho ViewBag là không có vấn đề gì bình thường:

ViewBag.property1 = 0; 
    ViewBag.property1 = "zero"; 

hoạt động tốt. ViewBag là động. Bây giờ, bạn có thể nhận được lỗi đó nếu sau này bạn sẽ cố gắng để giả mạo ViewBag.ddlUserId vào một cái gì đó thực sự là loại sai.

Tôi cũng muốn bạn viết lại tuyên bố của mình, hãy để tôi giải thích lý do. Giả sử trong một khoảnh khắc bạn có rất nhiều (> 100.000) bản ghi số User trong số db.Users của mình và chúng tôi giả định tương tự cho Fi. Trong mã của bạn, result1result2 hiện là hai danh sách, một danh sách chứa> 100.000 User đối tượng và một đối tượng khác> 100.000 Fi đối tượng. Sau đó, hai danh sách này được so sánh với nhau để tạo ra một danh sách các chuỗi. Bây giờ hãy tưởng tượng tài nguyên cần thiết cho máy chủ web của bạn để xử lý việc này. Theo giả định rằng bạn thực sự sử dụng/truy cập vào một máy chủ SQL riêng biệt để truy xuất dữ liệu của bạn, nó sẽ tốt hơn và nhanh hơn để cho máy chủ đó thực hiện công việc, tức là tạo danh sách UserID. Cho rằng bạn có muốn sử dụng câu trả lời Kirill Bestemyanov hay như sau:

var list = (from user in db.Users 
       where !db.Fi.Any(f => f.UserID == user.UserID) 
       select user.UserName).ToList() 

này sẽ sản xuất chỉ là một truy vấn cho các máy chủ SQL để thực hiện:

SELECT 
    [Extent1].[UserName] AS [UserName] 
    FROM [dbo].[Users] AS [Extent1] 
    WHERE NOT EXISTS (SELECT 
     1 AS [C1] 
    FROM [dbo].[Fi] AS [Extent2] 
    WHERE [Extent2].[UserID] = [Extent1].[UserID] 
    )} 

mà cuối cùng là những gì bạn muốn ...

Chỉ cần làm rõ hơn:

var list = (from user in db.Users 
       where !db.Fi.Any(f => f.UserID == user.UserID) 
       select user.UserName).ToList() 

có thể được viết như biểu thức sau đây lambda cũng như:

var list = db.Users.Where(user => !db.Fi.Any(f => f.UserID == user.UserID)) 
       .Select(user => user.UserName).ToList() 

mà từ vẻ của nó hơi khác so với câu trả lời Kirill Bestemyanov của (mà tôi chút thay đổi, chỉ để làm cho nó trông giống hơn):

var list = db.Users.Where(user => !db.Fi.Select(f => f.UserID) 
              .Contains(user.UserID)) 
           .Select(user => user.UserName).ToList(); 

Nhưng, trên thực tế, chúng sẽ tạo ra cùng một câu lệnh SQL, do đó cùng một danh sách.

3

Tôi sẽ viết lại nó để phương pháp khuyến nông LINQ:

List<string> listString = db.Users.Where(e=>!db.Fi.Select(m=>m.UserID) 
                .Contains(e.UserID)) 
            .Select(e=>e.UserName).ToList(); 

thử nó, nó sẽ làm việc.

+0

Tôi đã lo lắng điều này sẽ tạo ra một loạt các cuộc gọi SQL, nhưng nó chuyển đổi nó thành SQL phù hợp nhờ! – Nico

4

Hãy thử tính năng này rất đơn giản.

var result=(from e in db.Users 
      select e.UserID).Except(from m in db.Fi 
            select m.UserID).ToList(); 
Các vấn đề liên quan