2009-09-02 5 views
6

J'ai un modèle au-dessus de mon modèle de base de données et mappe les objets dans mon dépôt. Cependant, apparemment, cela fait une différence si je "sélectionne" directement dans mes GetUsers ou "select factoryresult" comme implémenté ci-dessous. J'obtiens l'erreur à l'exécution, que la méthode CreateFromDbModel n'a pas de traduction en sql (System.NotSupportedException).Comment utiliser les classes de fabrique avec linq pour sql?

Y a-t-il un moyen de contourner cela? Puis-je le réparer d'une manière ou d'une autre?

La raison de vouloir utiliser la méthode de fabrication est que je pourrais instancier des objets ailleurs et que vous souhaitez garder le « code de mappage » dans un endroit ...

Merci pour tous les commentaires, 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 
        }; 
    } 

Répondre

1

Le problème est-il dû au fait que vous renvoyez IQueryable dans votre méthode GetUsers? Essayez de renvoyer la liste à la place. Cela forcera la requête Linq à s'exécuter dans la méthode.

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(); 
} 

Vous ne savez pas si cela va résoudre le problème, juste une intuition. J'ai été capable de dupliquer ce que vous faites dans Linqpad sur une base de données locale, et cela a fonctionné. Mais mon échantillon ne retournait pas un IQueryable. Modifiez-vous la collection IQueryable en dehors de GetUsers()?

Edit:

je l'ai fait d'autres vérifications. Je suis en mesure de reproduire l'erreur que lorsque je modifié mon échantillon pour la collection IQueryable a été utilisé dans une deuxième requête Linq après avoir appelé GetUsers():

IQueryable<User> query = GetUsers(true); 

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

Je parie que si vous retournerez une liste comme suggéré ci-dessus dans GetUsers() l'erreur disparaîtra. Le seul inconvénient est que tout filtrage effectué après l'appel de GetUsers() ne limite pas la quantité de données renvoyées par la base de données car vous avez déjà exécuté la requête lors de l'appel de .ToList().

Edit 2:

Malheureusement, je ne pense pas qu'il y ait une autre façon d'inclure votre méthode d'usine dans la requête. J'ai une idée de plus. Vous pouvez créer une méthode d'extension pour IQueryable, appelez-la comme ToUserList(). Dans ToUserList(), vous appelez ToList() sur la requête et votre méthode d'usine qui renvoie une collection d'utilisateurs. Appelez cette méthode lorsque vous avez terminé de filtrer les données à l'aide de Linq. Cela vous permettra d'exécuter la requête uniquement lorsque vous êtes prêt à charger les données de la base de données. Un exemple est donné ci-dessous.

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

Appelez la méthode d'extension comme ceci:

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

Hope this sens. Douglas H.

+0

Merci Douglas et Rossisdead, J'ai essayé de convertir en liste avant d'appeler ma méthode d'usine, mais non seulement dois-je retourner tout le linq objets de la base de données, je dois aussi construire tous mes objets de modèle de domaine - et j'essayais de trouver un moyen qui n'exige pas cela ... En outre, je fais le filtrage dans ma couche de service et je vais devoir interrogeable. ... –

+0

Hi Anders, Voir Edit 2 ci-dessus. – Douglas

+0

Salut Douglas, Je marque votre réponse comme la réponse, mais j'espérais conserver les objets linq de la base de données dans la couche de données où votre suggestion exposerait les objets de la couche de données à la couche de service. –

1

L'erreur explique à peu près tout.

"La méthode CreateFromDbModel n'a pas de traduction en sql (System.NotSupportedException) "

Votre méthode CreateFromDbModel n'est pas une fonction sql Votre application ne pourra pas exécuter la fonction CreateFromDbModel tant que les objets ne vous auront pas été renvoyés par le serveur. ToList() ou quelque chose de similaire sur votre requête avant que vous pouvez exécuter CreateFromDbModel sur eux

Questions connexes