8
votes

Méthode de classe d'appel à l'intérieur de la requête LINQ

J'ai une méthode appelée godetage (anniversaire DateTime). Je souhaite utiliser cette méthode dans la requête de Linq en passant l'anniversaire et en fonction de la valeur de l'âge de retour nécessaire pour perfromer une certaine logique.

Je veux en dessous de la requête en format LINQ - P>

  from customer in contetx.Customer where 
  if GetAge(customer.BirthDate) > 20 and customer.accountType="Savings"
  or
  if(GetAge(customer.BirthDate) > 40 and customer.AccountType="Current"


1 commentaires

C'est LINQ aux entités. J'utilise le cadre d'entité.


3 Réponses :


11
votes
var customers = from customer in contetx.Customer 
                let age = GetAge(customer.BirthDate)
                where (age > 20 && customer.accountType == "Savings") ||
                      (age > 40 && customer.accountType == "Current")
                select customer;

6 commentaires

Oui, il évite de recalculer deux fois l'âge.


heyy c'est génial ... je ne sais pas 'laisser "mot clé .. Darin u r champion ... Merci beaucoup sauvé beaucoup de mon temps ...


Darin une question .. Ci-dessous Dave a pointé que "parce que le problème est la méthode que vous appelez n'existe que dans votre code, la base de données ne sait pas ce qu'elle est", cela peut lancer une exception .. Pensez-vous dans ce cas Laissez le mot clé Wud fonctionner .. Je vais l'essayer et mettre à jour le post .. mais je pensais simplement à vérifier avec vous, si vous avez des entrées ...


Bonjour Darin, j'ai essayé de cette façon mais obtenez une exception comme ci-dessous - Linq aux entités ne reconnaît pas la méthode 'int32 godetage (System.DateTime`1 [System.DateTime])' ', et cette méthode ne peut pas être traduite dans une expression de magasin.


Cela fonctionnera, mais le filtrage sera effectué du côté du client, ce qui signifie que tous les clients seront extraits de la base de données. Je suggérerais d'implémenter une godee sur le serveur d'une certaine manière, par exemple, une colonne calculée ou quelque chose.


J'aimerais connaître le scénario où le mot-clé "let" fonctionnerait. Ci-dessous Query Working Working - var requête du client dans // ... Laisser l'âge = godetage (client.birthdate) où // ... Sélectionnez le client; Erreur: "Linq aux entités ne reconnaît pas la méthode 'int32 godetage (System.Lullable`1 [System.DateTime])' méthode, et cette méthode ne peut pas être traduite dans une expression de magasin."



0
votes

Vous pouvez le faire:

var query from customer in // ...
    let age = GetAge(customer.BirthDate)
    where // ...
select customer; 


7 commentaires

Est-ce possible d'avoir deux clauses comme celle-ci?


non ce n'est pas. La requête doit fonctionner si vous supprimez le deuxième


Vous pouvez obtenir des résultats étranges avec celle où, vous devez entre les parenthèses des première et seconde pour vous assurer ou les exploiter correctement.


Je reçois ci-dessous une exception avec la requête ci-dessus "Linq aux entités ne reconnaît pas la méthode" int32 godetage (System.Nullable`1 [System.DateTime]) '' méthode, et cette méthode ne peut pas être traduite dans une expression de magasin. "


Non, pas encore .. mais cherchait une option pour faire quelque chose comme Dave pointant pour utiliser les méthodes d'extension. Mais ne savez vraiment pas utiliser les méthodes d'extension dans la requête LINQ. Comment puis-je convertir la méthode statique de mon godet (DateTime Birtdate) dans la méthode d'extension, puis utilisez-la dans la requête supérieure ...


Ajoutez un exemple de votre méthode godet car il s'agit actuellement de la question initiale et je vais jeter un oeil, voir si je peux améliorer ma réponse.


Public static int getage (DateTime? Anniversaire) {if (! Anniversaire.hasvalue) {retour -1; } int épandes = anniversaire.value.timepan; int diff tffriespan = datetime.today.timepan - Timespan; RETOUR DE DIFFTHTISPAN / 365; } Voici ma méthode godet.



9
votes
public static IQueryable<Customer> WhoAreValidByAge(this IQueryable<Customer> customers)
{
    cusomters.Select(c => new { Customer = c, Age = (DateTime.Today.Year - c.BirthDate.Year) }
             .Where(c => (c.Age > 20 && c.Customer.AccountType == "Savings")
                      || (c.Age > 40 && c.Customer.AccountType == "Current"))
             .Select(c => c.Customer)
}

10 commentaires

Je ne pense pas qu'il soit nécessaire d'appeler asen-témoine () .


Il fonctionne directement sur le contexte en utilisant une méthode qui, autant que je sache, étant donné les informations de la question, n'a aucune traduction directe à SQL. S'il ne se convertit pas en LinqtoObjects (en utilisant .asenumable () ou .tolist ()), essayant d'accéder aux informations renvoyées par la requête jettera une notaupportedexception avec la méthode de message 'godetage' n'a pas de traduction prise en charge sur SQL ...


L'appel approprié asen-tueuse peut extraire inutilement toutes les données à ce moment-là dans la base de la base de données.


Oui, mais c'est inévitable si vous utilisez une méthode qui n'existe que dans votre code. Lorsque vous essayez d'exécuter les autres requêtes, vous obtiendrez une exception si vous essayez d'utiliser une méthode qui ne peut pas être convertie en SQL.


Ouais tu as raison, je reçois le wrror que tu as mentionné si je n'utilise pas l'asen-témoine () .. mais je vais utiliser asen-tumérable à ce moment-là que la base de données a 2 lakhs de ces clients..it tuera mon application..veuillez suggérer si Vous êtes au courant de tout autre moyen .. Pensez-vous que la clé de la clé fonctionnera ici comme indiquée par Darin dans la première réponse ??


Non, car le problème est la méthode que vous appelez n'existe que dans votre code, la base de données ne sait pas ce que c'est ... je vais mettre à jour ma réponse avec une alternative possible


Merci Dave pour une réponse rapide .. Juste pour ajouter que j'utilise l'entité Framework et MySQL en tant que base de données.


C'est excellent Dave, mais la godee n'est que l'exemple que j'ai donné, j'ai une méthode qui fait plus que je suppose que je ne peux pas être possible d'inclure tous à Linq ... mais cette idée est vraiment gr8 ..


J'ai ajouté une autre option: Utilisation de méthodes d'extension. À condition qu'ils fonctionnent sur des types iquérisables, le fait que c'est un appel de méthode ignorera et que le contenu sera évalué dans l'équivalent SQL. Le contenu aura toujours besoin d'être valide SQL mais vous pourrez peut-être masquer des sous-requêtes compliquées.


Merci beaucoup à nouveau Dave, c'est la bonne direction .. Je vais l'essayer et mettra à jour le fil en conséquence ..