Je travaille avec un client qui souhaite combiner LINQ à SQL avec sa couche DAL interne. En fin de compte, ils veulent être en mesure d'interroger leur couche en utilisant la syntaxe LINQ typique. Le point où cela devient délicat, c'est qu'ils construisent leurs requêtes de manière dynamique. Donc finalement ce que je veux, c'est pouvoir prendre une requête LINQ, la démonter et être capable d'inspecter les pièces pour sortir les bons objets, mais je ne veux pas vraiment construire une pièce pour traduire l'expression 'where' en SQL. Est-ce quelque chose que je peux juste générer en utilisant le code Microsoft? Ou y a-t-il un moyen plus facile de le faire?Extraction de la clause WHERE de LINQ to SQL
Répondre
(vous juste milieu LINQ, pas vraiment LINQ to SQL)
Bien sûr, vous pouvez le faire - mais il est des quantités massives de travail. Here's how; Je recommande "ne pas". Vous pouvez également regarder le code source pour DbLinq - voir comment ils le font.
Si vous voulez justeWhere
, il est un peu plus facile - mais dès que vous commencez à obtenir des jointures, groupements, etc - il sera très difficile à faire.
Voici justeWhere
support sur un implemention LINQ personnalisé (pas un fournisseur entièrement interrogeable, mais assez pour obtenir LINQ avec Where
de travail):
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace YourLibrary
{
public static class MyLinq
{
public static IEnumerable<T> Where<T>(
this IMyDal<T> dal,
Expression<Func<T, bool>> predicate)
{
BinaryExpression be = predicate.Body as BinaryExpression;
var me = be.Left as MemberExpression;
if(me == null) throw new InvalidOperationException("don't be silly");
if(me.Expression != predicate.Parameters[0]) throw new InvalidOperationException("direct properties only, please!");
string member = me.Member.Name;
object value;
switch (be.Right.NodeType)
{
case ExpressionType.Constant:
value = ((ConstantExpression)be.Right).Value;
break;
case ExpressionType.MemberAccess:
var constMemberAccess = ((MemberExpression)be.Right);
var capture = ((ConstantExpression)constMemberAccess.Expression).Value;
switch (constMemberAccess.Member.MemberType)
{
case MemberTypes.Field:
value = ((FieldInfo)constMemberAccess.Member).GetValue(capture);
break;
case MemberTypes.Property:
value = ((PropertyInfo)constMemberAccess.Member).GetValue(capture, null);
break;
default:
throw new InvalidOperationException("simple captures only, please");
}
break;
default:
throw new InvalidOperationException("more complexity");
}
return dal.Find(member, value);
}
}
public interface IMyDal<T>
{
IEnumerable<T> Find(string member, object value);
}
}
namespace MyCode
{
using YourLibrary;
static class Program
{
class Customer {
public string Name { get; set; }
public int Id { get; set; }
}
class CustomerDal : IMyDal<Customer>
{
public IEnumerable<Customer> Find(string member, object value)
{
Console.WriteLine("Your code here: " + member + " = " + value);
return new Customer[0];
}
}
static void Main()
{
var dal = new CustomerDal();
var qry = from cust in dal
where cust.Name == "abc"
select cust;
int id = int.Parse("123");
var qry2 = from cust in dal
where cust.Id == id // capture
select cust;
}
}
}
Je ne veux juste où. Je suis d'accord que le regroupement et les jointures sont hors de portée, et la société ne veut pas vraiment utiliser les données de cette façon de toute façon. Ils sont énormes pour extraire des objets complets de la base de données. En fin de compte, je pense que ce soit comme IEnumerable
OK; Je vais ajouter un exemple qui fait juste cela, alors. –
Je viens de lire un article intéressant sur Expression Trees, LINQ to SQL les utilise pour traduire la requête en SQL et l'envoyer sur le réseau.
Peut-être que c'est quelque chose que vous pourriez utiliser?
Techniquement si votre DAL expose IQueryable<T>
Au lieu de IEnumerable<T>
, vous pouvez également mettre en œuvre un IQueryProvider et faire exactement ce que vous décrivez. Cependant, ce n'est pas pour les faibles de cœur. Mais si vous exposez les tables LINQ to SQL elles-mêmes dans le DAL, elles feront exactement cela pour vous. Il y a un (grand) risque puisque vous manipulerez le contrôle total du code client sur la façon d'exprimer les requêtes SQL, et le résultat habituel est une requête complexe qui joint tout et qui pique la pagination avec un temps d'exécution moins que spectaculaire performance.
Je pense que vous devriez examiner attentivement ce qui est réellement nécessaire de la DAL et exposer seulement cela.
Juste un peu cependant. Je connais un support de langage qui construit une chaîne qui peut être exécutée dans le code lui-même. Je n'ai jamais essayé avec .Net, mais c'est commun dans les langages fonctionnels comme LISP. Depuis .Net support lambdas, peut-être que c'est possible. Puisque F # arrive bientôt sur .Net, peut-être que ce sera possible si ce n'est pas le cas maintenant. Ce que j'essaie de dire, c'est que si vous pouvez le faire, vous pouvez peut-être créer cette chaîne qui sera utilisée comme instruction LINQ, puis l'exécuter. Puisque c'est une chaîne, il sera possible d'analyser la chaîne et d'obtenir l'information que vous voulez.
Try Dynamic Linq
à quelqu'un d'autre avec la même question là-bas.Extraire la clause where de LINQ-to-SQL n'est pas aussi simple, comme on aurait pu l'espérer. De plus, faire cela par lui-même n'a probablement aucun sens. Il y a quelques options, selon les exigences - soit l'attraper à partir de la chaîne générée, mais alors il contiendrait des références de paramètres et des mappings de propriété d'objet qui devraient également être résolus, donc ceux-ci devraient également être retirés du fournisseur d'origine en quelque sorte, sinon ce serait inutile. Un autre - serait de trouver un fournisseur modulaire qui peut le faire, ainsi que rendre les mappages de membres facilement accessibles, mais encore une fois, sans le reste de la requête, je vois peu d'utilité à le faire, car la clause where référencer table/alias de colonnes de l'instruction select.
J'ai eu une tâche similaire d'écrire un fournisseur complet pour un ORM/DAL personnalisé il y a quelques années. Bien que cela soit considéré comme la chose la plus complexe sur laquelle j'ai travaillé, étant un développeur d'expérience, je peux dire que ce n'est pas aussi grave, comme le prétendent certaines personnes une fois que vous avez compris les concepts qui sont à la base. Certaines solutions que j'ai vues vont dans le mauvais sens, ajoutent des fonctionnalités redondantes et ont des problèmes d'adressage de code supplémentaires introduits par la logique sous-jacente. Par exemple. l'étape/module "optimisation" qui tente de recalculer le SQL imbriqué gonflé produit par l'analyseur principal. Si ce dernier était conçu de telle sorte qu'il produirait un SQL propre dès le début, aucune phase de nettoyage ne serait nécessaire. J'ai vu des fournisseurs qui créent un nouveau niveau d'imbrication pour chaque appel d'invocation. C'est une mauvaise stratégie. En décomposant une requête en trois/quatre parties principales - select, from, where et orderby, qui sont construites individuellement lors de la visite de l'arbre, ce problème est complètement évité. J'ai développé un objet-à-données (aka LINQ-to-SQL) fourni basé sur ces principes pour un ORM/DAL personnalisé et il produit un bon, propre SQL, avec une excellente performance, comme chaque déclaration est compilée à IL et mis en cache.
Pour tous ceux qui cherchent à faire quelque chose de similaire, veuillez consulter mes articles qui incluent un exemple de projet avec une implémentation tutorial/barebones qui permet de voir facilement comment cela fonctionne. Inclus aussi est la solution complète:
- 1. LINQ to Nhiberate - clause Where
- 2. .NET Linq to SQL: sélectionnez la moyenne avec where-clause
- 3. LINQ to SQL - types nullables dans la clause where
- 4. clause where dans LINQ to SQL fonction Sum()
- 5. C# Clause WHERE dynamique dans une requête LINQ to SQL
- 6. Ce qui est différent LINQ to SQL clause where
- 7. LINQ Join Where Clause
- 8. Linq 2 SQL - Générique clause where
- 9. Non-Passable Where Clauses LINQ-to-SQL
- 10. T-SQL généré à partir de LINQ to SQL manque une clause where
- 11. LINQ to Entities 4: Requête avec calcul dans where clause
- 12. Agréger dans where clause de LINQ
- 13. Comment puis-je écrire la clause "Where" dans la requête LINQ to SQL suivante?
- 14. linq to sql ne met pas de guillemets autour des chaînes dans where clause
- 15. T Clause SQL WHERE
- 16. Count clause SQL where
- 17. Linq inclure avec clause where
- 18. Linq Sous-requête Where Clause
- 19. LINQ to SQL génère des conditions négatives dans la clause WHERE
- 20. XML LinQ contient dans la clause WHERE
- 21. LINQ to Entities - Lorsque la clause IN dans la requête
- 22. Dynamic "WHERE IN" sur IQueryable (linq to SQL)
- 23. LINQ clause where pas dans l'instruction select
- 24. Passage d'une clause WHERE pour une requête Linq-to-Sql en tant que paramètre
- 25. LINQ to SQL - obtenir les dernières enregistrements qui correspondent à une clause where
- 26. LINQ to SQL - Comment ajouter une clause where à une jointure gauche?
- 27. Expressions complexes dans une clause LINQ Where
- 28. SQL Server: dynamique clause where
- 29. Comment créer une clause where dynamique en utilisant une liste dans LINQ to SQL?
- 30. clause where d'où la clause
exemple Ajouté par commentaire –