Il existe un type d'entité appelé produit qui est généré par le framework d'entité. J'ai écrit cette requête
public IQueryable<Product> GetProducts(int categoryID)
{
return from p in db.Products
where p.CategoryID== categoryID
select new Product { Name = p.Name};
}
Le code ci-dessous renvoie l'erreur suivante:
"L'entité ou le type complexe Shop.Product ne peut pas être construit dans une requête LINQ to Entities"
var products = productRepository.GetProducts(1).Tolist();
Mais quand j'utilise select p
au lieu de select new Product { Name = p.Name};
cela fonctionne correctement.
Comment puis-je préformer une section de sélection personnalisée?
c#
entity-framework
Ghooti Farangi
la source
la source
Réponses:
Vous ne pouvez pas (et ne devriez pas pouvoir) projeter sur une entité mappée. Vous pouvez cependant projeter sur un type anonyme ou sur un DTO :
Et votre méthode renverra une liste de DTO.
la source
Vous pouvez projeter dans un type anonyme, puis à partir de celui-ci vers le type de modèle
Éditer : Je vais être un peu plus précis car cette question a attiré beaucoup d'attention.
Vous ne pouvez pas projeter directement dans le type de modèle (restriction EF), il n'y a donc aucun moyen de contourner cela. La seule façon est de projeter en type anonyme (1ère itération), puis de modéliser le type (2ème itération).
Sachez également que lorsque vous chargez partiellement des entités de cette manière, elles ne peuvent pas être mises à jour, elles doivent donc rester détachées telles quelles.
Je n'ai jamais complètement compris pourquoi cela n'est pas possible, et les réponses sur ce fil ne donnent pas de raisons solides contre cela (parlant principalement de données partiellement chargées). Il est exact que, dans un état partiellement chargé, l'entité ne peut pas être mise à jour, mais alors, cette entité serait détachée, de sorte que des tentatives accidentelles de les enregistrer ne seraient pas possibles.
Considérez la méthode que j'ai utilisée ci-dessus: nous avons toujours une entité de modèle partiellement chargée. Cette entité est détachée.
Considérez ce code (souhait d'exister) possible:
Cela pourrait également entraîner une liste d'entités détachées, nous n'aurions donc pas besoin de faire deux itérations. Un compilateur serait intelligent de voir que AsNoTracking () a été utilisé, ce qui entraînera des entités détachées, il pourrait donc nous permettre de le faire. Si, cependant, AsNoTracking () était omis, il pourrait lever la même exception qu'il lance maintenant, pour nous avertir que nous devons être suffisamment précis sur le résultat que nous voulons.
la source
Il y a une autre façon dont j'ai trouvé que ça marche, vous devez construire une classe qui dérive de votre classe Product et l'utiliser. Par exemple:
Je ne sais pas si cela est "autorisé", mais cela fonctionne.
la source
Voici une façon de procéder sans déclarer de classe supplémentaire:
Cependant, cela ne doit être utilisé que si vous souhaitez combiner plusieurs entités en une seule entité. La fonctionnalité ci-dessus (cartographie simple de produit à produit) se fait comme suit:
la source
Un autre moyen simple :)
la source
.ToList
en requête, elle est exécutée et extraite des données du serveur alors à quoi bon la refaireAsQueryable
?.Vous pouvez l'utiliser et cela devrait fonctionner -> Vous devez utiliser
toList
avant de créer la nouvelle liste en utilisant select:la source
En réponse à l'autre question qui a été marquée comme doublon ( voir ici ), j'ai trouvé une solution rapide et facile basée sur la réponse de Soren:
Remarque: Cette solution ne fonctionne que si vous avez une propriété de navigation (clé étrangère) sur la classe Task (appelée ici «Incident»). Si vous ne l'avez pas, vous pouvez simplement utiliser l'une des autres solutions publiées avec "AsQueryable ()".
la source
Vous pouvez résoudre ce problème en utilisant des objets de transfert de données (DTO).
Ce sont un peu comme des modèles de vue où vous mettez les propriétés dont vous avez besoin et vous pouvez les mapper manuellement dans votre contrôleur ou en utilisant des solutions tierces comme AutoMapper.
Avec les DTO, vous pouvez:
J'ai appris cela à l'école cette année et c'est un outil très utile.
la source
Si vous utilisez le framework Entity, essayez de supprimer la propriété de DbContext qui utilise votre modèle complexe en tant qu'entité. J'ai eu le même problème lors du mappage de plusieurs modèles dans un modèle de vue nommé Entity
La suppression de l'entrée de DbContext a corrigé mon erreur.
la source
si vous exécutez,
Linq to Entity
vous ne pouvez pas utiliser leClassType
avecnew
dans laselect
fermeture de la requêteonly anonymous types are allowed (new without type)
regardez cet extrait de mon projet
vous avez ajouté la
new keyword
fermeture dans Select même sur lecomplex properties
vous obtiendrez cette erreurcar il sera transformé en instruction sql et exécuté sur SqlServer
alors quand puis-je l'utiliser
new with types
à laselect
fermeture?vous pouvez l'utiliser si vous avez affaire à
LINQ to Object (in memory collection)
après avoir exécuté
ToList
sur requête, il est devenuin memory collection
que nous pouvons utilisernew ClassTypes
dans certainsla source
Dans de nombreux cas, la transformation n'est pas nécessaire. Pensez à la raison pour laquelle vous voulez fortement taper List et évaluez si vous voulez simplement les données, par exemple, dans un service Web ou pour les afficher. Peu importe le type. Vous avez juste besoin de savoir comment le lire et vérifier qu'il est identique aux propriétés définies dans le type anonyme que vous avez défini. C'est le scénario optimun, car quelque chose dont vous n'avez pas besoin de tous les champs d'une entité, et c'est la raison pour laquelle le type anonyme existe.
Une façon simple de procéder est la suivante:
la source
Il ne vous permettra pas de mapper à nouveau sur Product car c'est votre table que vous interrogez. Vous avez besoin d'une fonction anonyme, vous pouvez ensuite l'ajouter à un ViewModel, ajouter chaque ViewModel à un
List<MyViewModel>
et les renvoyer. C'est une légère digression, mais j'inclus des mises en garde sur la gestion des dates annulables car elles sont difficiles à gérer, au cas où vous en auriez. C'est ainsi que je l'ai géré.J'espère que vous avez
ProductViewModel
:J'ai un cadre d'injection de dépendances / référentiel où j'appelle une fonction pour récupérer mes données. En utilisant votre article comme exemple, dans votre appel de fonction Controller, cela ressemblerait à ceci:
Dans la classe de référentiel:
De retour dans le contrôleur, vous faites:
la source
ajoutez seulement AsEnumerable ():
la source
vous pouvez ajouter AsEnumerable à votre collection comme suit:
la source