Linq, Expression et Compiled Queries - C#/.NET managed - Programmation
Marsh Posté le 30-09-2013 à 16:48:32
Avec des jointures plutôt que des sous requetes...
En plus d'être moins lourd à coder, ça sera beaucoup² plus perfomant :
Code :
|
Marsh Posté le 30-09-2013 à 16:58:05
Mieux encore, car j'ai l'impression que tu cherchais à réaliser une Left outer join, la version exacte est :
Code :
|
Marsh Posté le 30-09-2013 à 17:21:41
Merci mon cher ixemul
Mais ce que tu me proposes la est un brin trop basique et c'est ce que je faisais jusqu'à maintenant
Mon but est d'avoir une CompiledQuery ou une expression qui me permettrait de faire un GetCompanyById tout en réinjectant cette requete dans diverse requete ou j'ai besoin de l'objet company
Un exemple un peu plus parlant:
J'ai un objet contrat
cet objet possède n attributs dont 4 qui sont de meme type mais différent (4 entité légales)
Avec ma vieille méthode je me tapais une requete compilé pour récupérer un entitié légale par Id et dans le get contract j'étais obligé de copier quatre fois cette portion de code.
Pas propre pour la maintenance...
Le but est d'avoir une expression que je puisse réinjecter à la construction de la compiled query comme ça si l'objet est modifié je n'ai qu'un point dans toute l'application et non pas 20 dont certains dans des compiled queries de 700 lignes
Marsh Posté le 01-10-2013 à 10:03:08
Ok, je comprends mieux ce que tu veux faire.
Je decele un petit soucis dans ton 2eme exemple,
ublic static Func<MonContext, int, MonTypeCompany> GetCompanyById = CompiledQuery.Compile<MonContext, int, MonTypeCompany>
(context, id) =>
(from company in context.COMPANY
where company.Id == entite.FKCompany
select new MonTypeCompany
{
Id = company.Id,
Name = company.Name
}).FirstOrDefault());
Là, en rouge, ce devrait être id et non entite.FKCompany.
ça ne marche pas mieux ? dsl, je ne peux pas tester, ici je bosse avec Sybase et nous n'avons pas de connecteur pour entity Framework...
Sinon, en l'absence de solution, tu peux te tourner vers de la génération de code via T4 (langage de template MS intégré à visual studio). Cela te permettrai de maintenir uniquement le script de génération et laisserai la génération de la partie lourde du code au templating.
Marsh Posté le 01-10-2013 à 11:47:26
oui pardon c'etait bien Id, mauvais CC
Je ne pense pas qu'il soit possible de générer des RC via template mon but était plus d'injecter des portions de code (Expression ou appel de Func) dans Linq to SQL, il semble que ce ne soit pas possible en l'état.
Je vais regarder du côté de ExpressionVisitor
Marsh Posté le 01-10-2013 à 11:51:42
snipeangel a écrit : oui pardon c'etait bien Id, mauvais CC |
Le soucis que tu mets en évidence, c'est que tu parts sur des requête compilée, c.à.d, du SQL qui sera généré à partir de ta requête LINQ, qui elle même sera compilée.
En faisant ce que tu propose, je vois mal comment l'injection d'une requête précompilée (Select Company) sera injectée dans une nouvelle requête (Select entite).
Il est possible de générer tes requetes par Template, le code sera simplement généré (t'épargnant la saisie de tes 700 tables), et simplement compilé avec le reste
Marsh Posté le 01-10-2013 à 12:01:16
Un autre exemple qui devrait de permettre de mieux comprendre ce que je cherche à faire
Code :
|
la classe BOLocationInfos contenant un objet type
Code :
|
et comment je récupère l'objet
Code :
|
l'exception catchée "Le type de nœud « Invoke » de l'expression LINQ n'est pas pris en charge dans LINQ to Entities."
C'est clairement une opération non supportée par Linq et je cherche à contourner ce problème
Au temps/autant pour moi
Tu as répondu pendant que je CC du code.
Il doit etre possible de faire reconnaitre à Linq qu'il doit utiliser une autre portion de code maintenant le tout c'est de trouver comment quitte à forcer la précompilation des requêtes pour qu'il puisse utiliser le code SQL généré
De toute faaçon les requêtes sont statiques.
Marsh Posté le 01-10-2013 à 14:04:13
Une autre approche serait en génération de code au runtime, perso, j'adore le faire, mais :
1- C'est très dangereux si mal maitrisé
2- C'est assez chaud pour les non initiés.
Le but étant de générer pendant le runtime tes méthodes d'accès au données en injectant le code compilé des méthode d'accès de base
Sinon, tu la joue facile avec LinqKit qui semble permettre de faire ce que tu veux faire :
http://www.albahari.com/nutshell/linqkit.aspx
Marsh Posté le 01-10-2013 à 14:23:29
Ta solution me plait bien va falloir que je regarde comment faire ça
pour LinqKit j' y ai jeté un œil "rapidement" hier et il semble que ça se limite aux "predicate" or ce qui m’intéresse c'est l'attribution de propriétés et non les clauses de recherche qui elles sont fixes (tout du moins pour le moment ) peut être que d'ici quelques temps je verrais un intérêt à aussi séparer les predicate .
Marsh Posté le 26-03-2014 à 15:34:22
Bon sinon au cas ou pour ceux qui auraient le même soucis, une petite modif de linqkit permet de faire tout ça très bien.
On peu du coup "injecter" des expressions dans des expressions sur autant de niveaux qu'on le désire
Marsh Posté le 26-03-2014 à 15:37:06
ha bha voila !
Marsh Posté le 06-05-2014 à 13:54:01
snipeangel a écrit : Bon sinon au cas ou pour ceux qui auraient le même soucis, une petite modif de linqkit permet de faire tout ça très bien. |
Dis-nous en plus ...
Marsh Posté le 30-09-2013 à 14:59:57
Une petite question pour les gourous du C#
J'utilise l'entity framework en ORM et des requêtes compilée pour les requêtes DB (Perfs + me permettent de ressortir directement les "types" d'objet dont j'ai besoin).
Pour "simplifier" la maintenance du code j'aurais voulu décomposer mes compiled queries en expression et "sous" expression
Ex j'ai une entité légale qui possède 3 propriétés, un Id, un Nom et un objet Company.
ma Company à 2 propriétés, un Id, un Nom
Classiquement j'ecrirais
Et j'appellerais ma compiled query en lui passant les params, on est d'accord que ça fonctionne très bien, par contre avec beaucoup d'objets imbriqués ça devient une vraie purge (700 ligne de requête merci mais sans façon...)
donc j'aurais voulu faire
mais malheureusement ça n'a pas l'air supporté par EF... J'ai aussi essayé de remplacer les compiled queries par des System.Linq.Expressions.Expression mais ça ne fonctionne pas mieux.
Apparemment je ne peux pas générer de CompiledQuery de façon dynamique, une idée pour contourner le problème?
Merci
Message édité par snipeangel le 30-09-2013 à 15:17:36
---------------
http://forum.hardware.fr/hfr/Achat [...] 0043_1.htm