Ne AutoMapper soutien Linq?
Je suis très intéressé par Linq to SQL avec Lazy caractéristique de charge. Et dans mon projet j'ai utilisé AutoMapper à la carte DB Modèle de Modèle de Domaine (à partir de DB_RoleInfo
à DO_RoleInfo
). Dans mon référentiel de code comme ci-dessous:
public DO_RoleInfo SelectByKey(Guid Key)
{
return SelectAll().Where(x => x.Id == Key).SingleOrDefault();
}
public IQueryable<DO_RoleInfo> SelectAll()
{
Mapper.CreateMap<DB_RoleInfo, DO_RoleInfo>();
return from role in _ctx.DB_RoleInfo
select Mapper.Map<DB_RoleInfo, DO_RoleInfo>(role);
}
SelectAll
méthode est de fonctionner bien, mais quand je l'appelle SelectByKey
, j'obtiens l'erreur:
Méthode “RealMVC.Les données.DO_RoleInfo MapDB_RoleInfo,DO_RoleInfo” pourrait ne pas se traduire par SQL.
Est-ce que Automapper ne prend pas en charge Linq complètement?
Au lieu de Automapper, j'ai essayé le manuel de cartographie de code ci-dessous:
public IQueryable<DO_RoleInfo> SelectAll()
{
return from role in _ctx.DB_RoleInfo
select new DO_RoleInfo
{
Id = role.id,
name = role.name,
code = role.code
};
}
Cette méthode fonctionne de la manière que je veux.
- Juste une remarque sur votre mise à jour en plus de ma réponse: La deuxième version fonctionne parce que Linq to SQL sait déjà que vous avez fait irréversible de projection; la
SelectByKey
est en fait tout simplement à l'aide de Linq to Objects. Si vous examiner la requête générée, je pense que vous trouverez que c'est encore la sélection de l'ensemble des entités de la base de données, ce qui est équivalent à l'utilisation deToList()
et puis filtrage de la liste résultante. - Ce n'est pas que AutoMapper prend en charge LINQ. C'est que LINQ to SQL ne prend pas en charge AutoMapper. Le LINQ to SQL de la requête fournisseur de recherche à l'expression de l'arbre pour déterminer la façon de générer la requête SQL. Quand il arrive à le Mappeur.Morceau de carte, il n'a aucune idée de la façon de générer le SQL.
Vous devez vous connecter pour publier un commentaire.
Tandis que @Aaronaught réponse était correcte au moment de l'écriture, comme souvent, le monde a changé et AutoMapper avec elle. Dans le même temps,
QueryableExtensions
ont été ajoutés à la base de code qui a ajouté le support pour les projections qui se traduit dans les expressions et, enfin, SQL.La base de la méthode d'extension est
ProjectTo
1. C'est ce que votre code pourrait ressembler à:et il se comporte comme le manuel de la cartographie. (Le
CreateMap
déclaration est ici pour les besoins de la démonstration. Normalement, vous seriez définir des mappages une fois au démarrage de l'application).Ainsi, seules les colonnes qui sont nécessaires pour la cartographie sont interrogés et le résultat est un
IQueryable
qui a encore de la requête d'origine fournisseur (linq-to-sql, linq-to-entités, quelle que soit). Donc, il est toujours modulable et cela va se traduire par uneWHERE
clause SQL:1
Project().To<T>()
avant v. 4.1.0SelectAll().SingleOrDefault(x => x.Id == Key);
Changer votre deuxième fonction de cette:
AutoMapper fonctionne très bien avec Linq to SQL, mais il ne peut pas être exécuté dans le cadre de la différés requête. L'ajout de
ToList()
à la fin de votre requête Linq provoque immédiatement évaluer les résultats, au lieu d'essayer de traduire le AutoMapper segment de la requête.Clarification
La notion de exécution différée (pas "lazy load") n'a aucun sens une fois que vous avez changé le type résultant de quelque chose qui n'est pas une entité de données. Tenir compte de ces deux classes:
Considérons maintenant le mappage suivant:
Cette cartographie est tout à fait acceptable (à moins que j'ai fait une faute de frappe), mais disons que vous écrivez le
SelectAll
méthode dans votre post original à la place de mon révisé:Au fait, ce type de travaux, mais en appelant lui-même un "interrogeable", il se trouve. Qu'advient-il si j'essaie d'écrire ce contre elle:
Pense vraiment dur à ce sujet. Comment pourrait-Linq to SQL éventuellement être en mesure de réussir à transformer votre
where
dans une base de données de la requête?Linq ne sait rien à propos de la
DO_RoleInfo
classe. Il ne sait pas comment faire la cartographie arrière - dans certains cas, cela peut même pas possible. Bien sûr, vous pouvez regarder ce code et accédez "Oh, c'est facile, il suffit de la recherche pour "Administrateur" ou "Général" dans laName
colonne", mais vous êtes le seul qui sait. Aussi loin que Linq to SQL, la requête est un pur non-sens.Imaginez que quelqu'un vous a donné ces instructions:
À moins que vous l'avez fait avant, et la plupart des gens n'ont pas, votre réponse à cette instruction n'est plus susceptible d'être:
Vous pouvez aller sur le marché, et vous pouvez obtenir des ingrédients spécifiques par son nom, mais vous ne pouvez pas évaluer la condition que je vous ai donné pendant que vous êtes là-bas,. J'ai "un" plan les critères première. Je dois vous dire, voici les ingrédients dont nous avons besoin pour cette recette - maintenant, allez et obtenir.
Pour résumer, ce n'est pas une simple incompatibilité entre Linq to SQL et AutoMapper. Il n'est pas unique à l'une de ces deux bibliothèques. Il n'a pas d'importance comment vous avez réellement faire le mappage à un non-type d'entité - vous pourriez tout aussi bien faire la cartographie manuellement, et vous obtenez toujours la même erreur, parce que vous êtes maintenant donner Linq to SQL un ensemble d'instructions qui ne sont plus compréhensibles, de traiter avec les mystérieux classes qui n'ont pas une valeur intrinsèque de la cartographie à un type d'entité.
Cette question est fondamentale dans le concept de Mappage O/R et reporté l'exécution de la requête. Un projection est un opération. Une fois que vous avez un projet, vous ne pouvez plus revenir en arrière de le moteur de requête et de dire oh, en passant, voici un peu plus les conditions pour vous. Il est trop tard. Le meilleur que vous pouvez faire est de prendre ce qu'il vous ai déjà donné et d'évaluer les conditions supplémentaires vous-même.
Dernier mais non le moins, je vais vous laisser avec une solution de contournement. Si le seulement chose que vous voulez être en mesure de faire à partir de votre cartographie est filtre les lignes, vous pouvez écrire ceci:
C'est une méthode utilitaire qui gère la cartographie pour vous et accepte un filtre sur le original entité, et pas mappés entité. Il pourrait être utile si vous avez beaucoup de différents types de filtres mais il faut toujours faire la même cartographie.
Personnellement, je pense que vous serez mieux l'écrire les requêtes correctement, en commençant par déterminer ce dont vous avez besoin pour récupérer à partir de la base de données, puis de faire des prévisions/mappings, et puis, enfin, si vous avez besoin de faire plus de filtrage (qui ne convient pas), puis matérialisent les résultats avec
ToList()
ouToArray()
et écrire plus de conditions à l'encontre de la liste locale.N'essayez pas d'utiliser AutoMapper ou tout autre outil pour cacher les véritables entités exposées par Linq to SQL. Le modèle de domaine est votre interface publique. Les requêtes que vous écrivez sont un aspect de votre privé de la mise en œuvre. Il est important de comprendre la différence et de maintenir une bonne séparation des préoccupations.