À la suite de l'excellente réponse à ma question précédente:Linq Entity Framework - puis-je utiliser une méthode récursive?
Linq Entity Framework generic filter method
J'essaie maintenant de comprendre comment je peux appliquer quelque chose comme récursion à ma solution.
Pour récapituler, au lieu de plusieurs déclarations similaires de cette méthode:
protected IQueryable<Database.Product> GetActiveProducts(ObjectSet<Database.Product> products) {
var allowedStates = new string[] { "Active" , "Pending" };
return (
from product in products
where allowedStates.Contains(product.State)
&& product.Hidden == "No"
select product
);
}
J'ai maintenant une seule application qui accepte un type d'interface (IHideable) pour fonctionner sur:
protected IQueryable<TEntity> GetActiveEntities<TEntity>(ObjectSet<TEntity> entities) where TEntity : class , Database.IHideable {
var allowedStates = new string[] { "Active" , "Pending" };
return (
from entity in entities
where allowedStates.Contains(entity.State)
&& entity.Hidden == "No"
select entity
);
}
Cela fonctionne bien et la solution est propre et compréhensible (grand merci à https://stackoverflow.com/users/263693/stephen-cleary). Ce que j'essaie de faire maintenant est d'appliquer une méthode similaire (ou la même?) À n'importe quelle EntityCollections associée à un EntityObject qui implémente aussi IHideable.
Je fais actuellement l'utilisation de GetActiveEntities() comme ceci:
var products = GetActiveEntities(Entities.Products);
return (
from product in products
let latestOrder = product.Orders.FirstOrDefault(
candidateOrder => (
candidateOrder.Date == product.Orders.Max(maxOrder => maxOrder.Date)
)
)
select new Product() {
Id = product.Id ,
Name = product.Name,
LatestOrder = new Order() {
Id = latestOrder.Id ,
Amount = latestOrder.Amount,
Date = latestOrder.Date
}
}
);
Dans cet exemple, je voudrais avoir les commandes EntityCollection filtrent aussi par GetActiveEntities(), de sorte que la dernière commande retournée ne peut jamais être "caché" un.
Est-il possible de filtrer toutes les EntityCollections implémentant IHideable - peut-être en appliquant un peu de réflexion/récursivité dans GetActiveEntities() et en appelant lui-même? Je dis récursion parce que la meilleure solution irait à plusieurs niveaux en marchant profondément à travers le graphe d'entité.
Ce truc étire mon cerveau!
MISE À JOUR # 1 (déplacé mes commentaires jusqu'ici)
Merci Steve.
Faire accepter la méthode IQuerable comme suggéré donne cette erreur:
'System.Data.Objects.DataClasses.EntityCollection<Database.Order>' does not contain a definition for 'GetActiveEntities' and no extension method 'GetActiveEntities' accepting a first argument of type 'System.Data.Objects.DataClasses.EntityCollection<Database.Order>' could be found (are you missing a using directive or an assembly reference?)
Je suppose que c'est parce que EntityCollection ne met pas en œuvre IQueryable.
J'ai été capable d'aller plus loin en créant une seconde méthode d'extension qui acceptait explicitement EntityCollection et renvoyait IEnumerable. Ce compilable mais lors de l'exécution a donné cette erreur:
LINQ to Entities does not recognize the method 'System.Collections.Generic.IEnumerable`1[Database.Order] GetActiveEntities[Order](System.Data.Objects.DataClasses.EntityCollection`1[Database.Order])' method, and this method cannot be translated into a store expression.
J'ai aussi essayé d'appeler AsQueryable() sur le EntityCollection et le retour IQueryable, mais la même erreur est revenue.
Merci pour la réponse Stephen. J'ai refactored la méthode dans une méthode d'extension plus tôt aujourd'hui, mais je ne voulais pas embourber cet exemple, donc utilisé un appel de méthode. Bon à savoir, c'était le bon choix - une grande partie de la fonctionnalité du langage C# est nouvelle pour moi. – FantasticJamieBurns
Merci Steve, j'ai déplacé mes commentaires à la zone de question pour une lecture plus facile ... – FantasticJamieBurns
Vous avez raison: 'EntityCollection' n'implémente pas' IQueryable'. J'ai mis à jour ma réponse pour utiliser 'Entities.Orders' plutôt que' product.Orders', ce qui devrait fonctionner. (J'ai aussi changé le calcul 'latestOrder' pour utiliser' orderby'). –