J'utilise le code d'abord dans ef. Disons que j'ai deux entités: mon dbcontext est quelque chose comme ceci: p> Je fais cela afin que chaque utilisateur puisse seulement voir Ses fermes, et je n'ai pas besoin d'appeler le lieu où sur chaque requête à la DB. P> Maintenant, je veux filtrer tous les fruits d'une ferme, j'ai essayé ceci (en classe agricole): mais la requête générée n'inclut pas la clause WHERE, qui est très importante car j'ai des dizaines de milliers de lignes et que cela n'est pas efficace pour les charger tous et les filtrer quand Ce sont des objets. P> J'ai lu que les propriétés chargées paresseuses sont remplies la première fois qu'elles sont accessibles, mais ils lisent toutes les données, aucun filtre ne peut être appliqué que si vous faites quelque chose comme ceci: P> from fruits in db.Fruits where fruit .... select fruit
3 Réponses :
Malheureusement, je pense que toute approche que vous pourriez prendre devrait impliquer de violer le contexte, pas seulement de l'entité. Comme vous l'avez vu, vous ne pouvez pas filtrer directement une propriété de navigation, car il s'agit d'un Une chose que vous pourriez éventuellement faire est de créer une propriété non mappée dans votre code> entité de ferme code> pour contenir la liste des fruits filtrés: P> < Pré> xxx pré> puis dans votre contexte / référentiel, ajoutez une méthode pour charger une entité code> entité code> et population qui devrait remplir Tout ce qui a dit, je pense que le fait que vous essayez de faire cela pourrait être un signe que vous mettez trop de logique commerciale dans votre classe d'entité, quand cela pourrait bien être meilleur dans une couche différente. Beaucoup de temps, il vaut mieux traiter des entités essentiellement comme des réceptacles pour le contenu d'un enregistrement de base de données et laisser tout le filtrage / traitement au référentiel ou où vit votre entreprise / logique. Je ne sais pas quel type d'application vous travaillez. Je ne peux donc pas vraiment proposer des conseils spécifiques, mais c'est quelque chose à penser. P> Une approche très courante si vous décidez de déplacer des choses L'entité ... puis utilisez les objets anonymes générés pour tout ce que vous voulez faire, plutôt que de Essayer d'ajouter des données supplémentaires aux entités code> agricole code> elles-mêmes. p> p> Icollection
iquéryable
filtréfruits code> avec les données souhaitées: p>
myfarm.filteredfruits code> avec seulement la collection filtrée, vous pouvez donc l'utiliser comme vous le souhaitez dans votre entité. Cependant, je n'ai jamais essayé cette approche moi-même, alors il peut y avoir des pièges que je ne pense pas. Un inconvénient majeur est qu'il ne fonctionnerait que avec
ferme code> Sous vous chargez d'utiliser cette méthode, et non avec des requêtes générales de Linq que vous effectuez sur le
mydbcontext.farms code> Dataset. P>
ferme code> est d'utiliser la projection: p>
Merci Jeremy, j'ai décidé de suivre vos conseils et de laisser les responsabilités de filtrage / traitement dans ma classe de contexte. Cela a du sens parce que je n'ai besoin que du filtrage pour une de mes entités, mais ce serait lourd si j'en avais besoin pour plusieurs entités, ne pensez-vous pas? Le contexte serait renseigné avec des méthodes de requête et de remplissage des entités. Je ne pense pas que cela brise le principe de responsabilité unique, mais cela semble plutôt étrange, n'est-ce pas?
Juste pensé que je voudrais ajouter une autre solution à ce après avoir passé quelque temps à essayer d'ajouter des principes DDD à premiers modèles de code. Après avoir cherché un certain temps que je trouve une solution comme celle ci-dessous qui fonctionne pour moi.
public class FruitFarmContext : DbContext { public DbSet<Farm> Farms { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Farm>().HasMany(Farm.FruitsExpression).WithMany(); } } public class Farm { public int Id { get; set; } protected virtual ICollection<Fruit> Fruits { get; set; } public static Expression<Func<Farm, ICollection<Fruit>>> FruitsExpression = x => x.Fruits; public IEnumerable<Fruit> FilteredFruits { get { //Apply any filter you want here on the fruits collection return Fruits.Where(x => true); } } } public class Fruit { public int Id { get; set; } }
Y a-t-il une implication avec cette solution?
Chargement paresseux ne prend pas en charge le filtrage; Utilisez Chargement explicite filtré à la place:
Farm farm = ( from farm in dbContext.Farms where farm.Owner == someOwner select new { Farm = farm, Fruit = dbContext.Fruit.Where(fruit => fruit.IsRipe) // Causes Farm.Fruit to be eager loaded }).Single().Farm;