2009-09-02 9 views
6

Ich habe ein Modell über meinem Datenbankmodell und mappe die Objekte in meinem Repository.Wie verwendet man Factory-Klassen mit linq für sql?

Offenbar macht es aber einen Unterschied, ob ich "neu" direkt in meinen GetUsers auswähle oder "Factory-Ergebnis auswählen" wie unten implementiert. Ich bekomme den Fehler zur Laufzeit, dass die Methode CreateFromDbModel keine Übersetzung in sql (System.NotSupportedException) hat.

Gibt es einen Weg um dies? Kann ich es irgendwie reparieren?

Der Grund für den Wunsch, die Factory-Methode zu verwenden, ist, dass ich Objekte an andere Stelle instanziiert könnte und den ‚Mapping-Code‘ an einem Ort halten will ...

Vielen Dank für alle Kommentare, 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 
        }; 
    } 

Antwort

1

Ist das Problem, weil Sie IQueryable in Ihrer GetUsers-Methode zurückgeben? Versuchen Sie stattdessen, List zurückzugeben. Dadurch wird die Linq-Abfrage innerhalb der Methode ausgeführt.

Nicht sicher, ob dies das Problem beheben wird, nur eine Ahnung. Ich konnte das, was Sie in Linqpad in einer lokalen Datenbank tun, duplizieren, und es funktionierte. Aber meine Probe gab kein IQueryable zurück. Möchten Sie die IQueryable-Sammlung auch außerhalb von GetUsers() ändern?

Edit:

Ich habe einige weitere Überprüfung durchgeführt. Ich konnte den Fehler nur kopieren, wenn ich meine Probe so modifiziert, dass die IQueryable Sammlung in einer zweiten Linq-Abfrage verwendet wurde nach GetUsers() aufrufen:

IQueryable<User> query = GetUsers(true); 

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

Ich wette, wenn Sie eine Liste zurückkehren wird, wie oben in GetUsers vorgeschlagen() Der Fehler wird verschwinden. Der einzige Nachteil ist, dass jede Filterung, die Sie nach dem Aufruf von GetUsers() ausführen, die Menge der von der Datenbank zurückgegebenen Daten nicht begrenzt, da Sie die Abfrage bereits beim Aufrufen von .ToList() ausgeführt haben.

Edit 2:

Leider Ihre Factory-Methode in der Abfrage zu enthalten sein Ich glaube nicht, dass es eine andere Art und Weise ist. Ich habe noch eine Idee. Sie können eine Erweiterungsmethode für IQueryable erstellen, rufen Sie es wie ToUserList() auf. In ToUserList() rufen Sie ToList() für die Abfrage und Ihre Factory-Methode auf, die eine Sammlung von Benutzern zurückgibt. Rufen Sie diese Methode auf, wenn Sie die Daten mit Linq gefiltert haben. Dadurch können Sie die Abfrage nur ausführen, wenn Sie bereit sind, die Daten aus der Datenbank zu laden. Ein Beispiel ist unten angegeben.

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

Rufen Sie die Extension-Methode wie folgt aus:

// 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. 

Hoffnung macht das Sinn. Douglas H.

+0

Dank Douglas und Rossisdead, Ich habe versucht, um zu listen, bevor ich meine Fabrikmethode nenne, aber nicht nur muss ich die ganze linq zurückgeben Objekte aus der Datenbank, ich muss auch alle meine Domänenmodellobjekte konstruieren - und ich habe versucht, einen Weg zu finden, der das nicht erfordert ... Außerdem mache ich Filterung in meiner Serviceebene und muss die Liste zurück in konvertieren abfragbar. ... –

+0

Hallo Anders, Siehe Bearbeiten 2 oben. – Douglas

+0

Hallo Douglas, Ich markiere deine Antwort als die Antwort, aber ich hatte gehofft, die Datenbank Linq Objekte in der Datenschicht zu halten, wo Ihr Vorschlag die Datenschicht Objekte der Service-Schicht ausgesetzt wäre. –

1

Der Fehler erklärt so ziemlich alles.

"Methode CreateFromDbModel hat keine Übersetzung in SQL (System.NotSupportedException) "

Ihre CreateFromDbModel-Methode ist keine SQL-Funktion. Ihre Anwendung kann die CreateFromDbModel-Funktion erst dann ausführen, wenn die Objekte vom Server zurückgegeben werden. Sie müssen höchstwahrscheinlich eine Verbindung herstellen ToList() oder etwas Ähnliches auf Ihrer Frage, bevor Sie CreateFromDbModel auf ihnen laufen lassen können.