2009-09-02 21 views
6

Ho un modello in cima al mio modello di database e mappa gli oggetti nel mio repository.Come utilizzare le classi factory con linq per sql?

Tuttavia, apparentemente fa la differenza se "selezionare nuovo" direttamente nel mio GetUsers o "selezionare factoryresult" come implementato di seguito. Ottengo l'errore in fase di esecuzione, che il metodo CreateFromDbModel non ha una traduzione in sql (System.NotSupportedException).

C'è un modo per aggirare questo? Posso ripararlo in qualche modo?

La ragione per voler utilizzare il metodo factory è che io possa instanciate oggetti altrove e vogliono mantenere il 'codice di mappatura' in un posto ...

Grazie per eventuali commenti, Anders

public IQueryable<User> GetUsers(bool includeTeams) 
    { 
     return from u in _db.sc_Players 
       where (includeTeams || (!u.aspnet_User.sc_Player.IsTeam)) 
       select UserFactory2.CreateFromDbModel(u); 
    } 


    public static User CreateFromDbModel(sc_Player player) 
    { 
     return new User 
        { 
         Id = player.sc_PlayerID, 
         FirstName = player.FirstName.Trim(), 
         LastName = player.LastName.Trim(), 
         PresentationName = player.FirstName.Trim() + " " + player.LastName.Trim(), 
         LoginName = player.aspnet_User.LoweredUserName, 
         IsTeam = player.IsTeam, 
         Email = player.aspnet_User.aspnet_Membership.Email, 
         Password = player.aspnet_User.aspnet_Membership.Password 
        }; 
    } 

risposta

1

Il problema è che si sta restituendo IQueryable nel metodo GetUsers? Prova invece a restituire l'elenco. Ciò imporrà la query Linq da eseguire all'interno del metodo.

public List<User> GetUsers(bool includeTeams) 
{ 
    return (from u in _db.sc_Players 
    where (includeTeams || (!u.aspnet_User.sc_Player.IsTeam)) 
    select UserFactory2.CreateFromDbModel(u)).ToList(); 
} 

Non so se questo risolverà il problema, solo un sospetto. Sono stato in grado di duplicare quello che stai facendo in Linqpad su un database locale, e ha funzionato. Ma il mio campione non stava restituendo un IQueryable. Stai modificando la raccolta IQueryable al di fuori di GetUsers()?

Edit:

ho fatto un po 'di controllo. Sono stato in grado di duplicare solo l'errore quando ho modificato il mio campione e così la raccolta IQueryable è stato utilizzato in una seconda query LINQ dopo aver chiamato getusers():

IQueryable<User> query = GetUsers(true); 

var q = from u in query 
    where u.Name.Contains("Bob") 
    select new {Name = u.FirstName + " " + u.LastName}; 

Scommetto che se si restituirà un elenco come suggerito sopra in getusers() l'errore andrà via. L'unico lato negativo è che qualsiasi filtraggio effettuato dopo aver chiamato GetUsers() non limiterà la quantità di dati restituiti dal database perché è già stata eseguita la query quando si chiama .ToList().

Edit 2:

Purtroppo non credo che ci sia altro modo per includere il metodo factory nella query. Ho ancora una idea. È possibile creare un metodo di estensione per IQueryable, chiamarlo qualcosa come ToUserList(). All'interno di ToUserList() si chiama ToList() sulla query e il metodo factory che restituisce una raccolta di utenti. Chiama questo metodo quando hai finito di filtrare i dati usando Linq. Ciò ti consentirà di eseguire la query solo quando sei pronto per caricare i dati dal database. Un esempio è dato seguito.

public static List<Users> ToUserList(this IQueryable<User> query) 
{ 
    return query.ToList().Select(u => UserFactory2.CreateFromDbModel(u)); 
} 

Chiamare il metodo di estensione in questo modo:

// Filter the data using linq. When you are ready to execute the query call: 
query.ToUserList(); // Query will execute and a list of User objects returned. 

Spero che questo ha un senso. Douglas H.

+0

Grazie Douglas e Rossisdead, ho provato a convertire alla lista prima di chiamare il mio metodo di fabbrica, ma non solo, devo restituire tutti i LINQ oggetti dal database, devo costruire anche tutti gli oggetti del mio modello di dominio - e stavo cercando di trovare un modo che non richiedesse questo ... Inoltre, faccio il filtraggio nel mio livello di servizio e dovrò riconvertire l'elenco in interrogabile. ... –

+0

Ciao Anders, Vedere Modifica 2 sopra. – Douglas

+0

Hi Douglas, Contrassegno la risposta come risposta, ma speravo di mantenere gli oggetti linq del database nel livello dati in cui il vostro suggerimento avrebbe esposto gli oggetti del livello dati al livello di servizio. –

1

L'errore spiega praticamente tutto.

"metodo CreateFromDbModel non ha una traduzione in sql (Sistema.NotSupportedException) "

Il metodo CreateFromDbModel non è una funzione sql. L'applicazione non sarà in grado di eseguire la funzione CreateFromDbModel fino a quando gli oggetti non verranno specificatamente restituiti dal server. ToList() o qualcosa di simile su vostra richiesta prima di poter eseguire CreateFromDbModel su di loro.