Je fais le didacticiel de pratique mvcmusicstore. J'ai remarqué quelque chose lors de la création de l'échafaudage pour le gestionnaire d'albums (ajouter supprimer modifier).
Je veux écrire du code avec élégance, donc je cherche la manière propre d'écrire ceci.
Pour info, je rends le magasin plus générique:
Albums = éléments
Genres = Catégories
Artiste = Marque
Voici comment l'index est récupéré (généré par MVC):
var items = db.Items.Include(i => i.Category).Include(i => i.Brand);
Voici comment l'élément à supprimer est récupéré:
Item item = db.Items.Find(id);
Le premier ramène tous les articles et remplit les modèles de catégorie et de marque à l'intérieur du modèle d'article. Le second ne remplit pas la catégorie et la marque.
Comment puis-je écrire le second pour faire la recherche ET remplir ce qu'il y a à l'intérieur (de préférence en 1 ligne) ... théoriquement - quelque chose comme:
Item item = db.Items.Find(id).Include(i => i.Category).Include(i => i.Brand);
la source
Réponses:
Vous devez d'
Include()
abord utiliser , puis récupérer un seul objet de la requête résultante:la source
La réponse de Dennis utilise
Include
etSingleOrDefault
. Ce dernier fait un aller-retour vers la base de données.Une alternative, est d'utiliser
Find
, en combinaison avecLoad
, pour le chargement explicite des entités liées ...Ci-dessous un exemple MSDN :
Bien sûr,
Find
retourne immédiatement sans faire de requête au magasin, si cette entité est déjà chargée par le contexte.la source
Find
donc si l'entité est présente, il n'y a pas d'aller-retour vers la base de données pour l'entité elle-même. MAIS, vous aurez un aller-retour pour chaque relation que vous êtesLoad
, alors que laSingleOrDefault
combinaison avecInclude
charge tout en une seule fois.Load
fonction, la relation doit être remplie au retour de l'appel. Donc, si vous appelezLoad
plusieurs fois pour plusieurs relations, il y aura un aller-retour à chaque fois. Même pour une seule relation, si laFind
méthode ne trouve pas l'entité en mémoire, elle effectue deux allers-retours: un pourFind
et le second pourLoad
. Mais leInclude
.SingleOrDefault
approche récupère l'entité et la relation en une seule fois pour autant que je sache (mais je ne suis pas sûr)Vous devez convertir IQueryable en DbSet
var dbSet = (DbSet<Item>) db.Set<Item>().Include("");
return dbSet.Find(id);
la source
Cela n'a pas fonctionné pour moi. Mais je l'ai résolu en faisant comme ça.
Je ne sais pas si c'est une bonne solution. Mais l'autre que Dennis m'a donné m'a donné une erreur booléenne
.SingleOrDefault(x => x.ItemId = id);
la source
SingleOrDefault(x => x.ItemId = id)
uniquement à cause du mauvais single=
au lieu du double==
?Il n'y a pas de moyen vraiment simple de filtrer avec une trouvaille. Mais j'ai trouvé un moyen rapproché de répliquer la fonctionnalité, mais veuillez prendre note de quelques éléments pour ma solution.
Cette solution vous permet de filtrer de manière générique sans connaître la clé primaire dans .net-core
Find est fondamentalement différent car il obtient l'entité si elle est présente dans le suivi avant d'interroger la base de données.
En outre, il peut filtrer par un objet afin que l'utilisateur n'ait pas à connaître la clé primaire.
Cette solution est pour EntityFramework Core.
Voici quelques méthodes d'extension à ajouter qui vous aideront à filtrer par clé primaire afin
Une fois que vous avez ces méthodes d'extension, vous pouvez filtrer comme suit:
la source