2013-04-27 14 views
5

Ciao ho il seguente codice per selezionare i dati da una tabella non in altra tabellaLinq per selezionare i dati da una tabella non in altra tabella

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 valore penetrino all'interno ListString .Ma ha errore nell'inserire la ListString a viewbag.

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

Controllare il tipo di dati di 'ddlUserId', potrebbe essere una mancata corrispondenza con una stringa! – zey

+0

Sembra che ViewBag.ddlUserId si aspetti un oggetto IEnumerable of User.ma il risultato della query è un elenco di stringhe –

+0

Penso che l'utente amministratore sia un enumeratore. – Amit

risposta

15

In primo luogo, è possibile aggiornare la domanda con l'intero metodo in modo che possiamo vedere cosa potrebbe accadere con il ViewBag? Perché il vostro codice dovrebbe funzionare bene, l'assegnazione di qualsiasi valore al ViewBag non è un problema di solito:

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

funziona bene. ViewBag è dinamico. Ora, potresti ottenere quell'errore se in un secondo momento proverai ad assegnare ViewBag.ddlUserId a qualcosa che in realtà è il tipo sbagliato.

Vorrei che anche tu riscrivi la tua dichiarazione, lasciami spiegare perché. Supponiamo per un momento di avere molti (> 100.000) di record User nel tuo db.Users e si ipotizza lo stesso per Fi. Nel tuo codice, result1 e result2 ora sono due elenchi, uno contenente> 100.000 oggetti User e l'altro> 100.000 oggetti Fi. Quindi questi due elenchi vengono confrontati l'uno con l'altro per produrre un elenco di stringhe. Ora immagina la risorsa richiesta per il tuo server web per elaborarla. Partendo dal presupposto che stai usando/accedendo effettivamente a un server SQL separato per recuperare i tuoi dati, sarebbe molto meglio e più veloce lasciare che quel server faccia il lavoro, cioè produrre l'elenco degli UserID. Per questo devi usare sia la risposta di Kirill Bestemyanov o il seguente:

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

Questo produrrà solo una query per il server SQL da eseguire:

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] 
    )} 

, che alla fine è ciò che si vuole ...

Giusto per chiarire di più:

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

può essere scritta come la seguente espressione lambda così:

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

che dagli sguardi di esso è leggermente diverso da risposta di Kirill Bestemyanov (che ho un po 'modificato, solo per farlo sembrare più simile):

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

Ma, in effetti, produrranno la stessa istruzione SQL, quindi la stessa lista.

3

io riscriverlo a metodi di estensione LINQ:

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

provarlo, dovrebbe funzionare.

+0

Ero preoccupato che questo avrebbe generato un sacco di chiamate SQL, ma lo ha convertito nel giusto SQL grazie! – Nico

4

Prova questo è molto semplice.

var result=(from e in db.Users 
      select e.UserID).Except(from m in db.Fi 
            select m.UserID).ToList(); 
Problemi correlati