Dynamique requête linq avec plusieurs inconnues critères
Je suis à la recherche de mettre en œuvre un système permettant d'utiliser que la "construction" des conditions et de retourner ensuite les données obtenues de la base de données. À l'heure actuelle, il existe une procédure stockée qui génère le SQL à la volée et l'exécute. C'est une question en particulier que je veux supprimer.
Mon problème vient du fait que je peux avoir plusieurs champs dans mes critères, et pour chacun de ces domaines, il pourrait y avoir 1 ou plusieurs valeurs, avec différents opérateurs potentiels.
Par exemple,
from t in Contacts
where t.Email == "[email protected]" || t.Email.Contains ("mydomain")
where t.Field1 == "valuewewant"
where t.Field2 != "valuewedontwant"
select t
Le terrain, les critères et l'opérateur sont stockées dans la base de données (et List<FieldCriteria>
) et serait quelque chose comme ceci (basé sur la ci-dessus);
Email, Equals, "[email protected]"
Email, Contains, "mydomain" Field1,
Equals, "valuewewant" Field2,
DoesNotEqual, "valuewedontwant"
ou
new FieldCriteria
{
FieldName = "Email",
Operator = 1,
Value = "[email protected]"
}
Donc, en utilisant les informations que j'ai, je veux être en mesure de construire une requête avec un certain nombre de conditions. J'ai vu des précédentes liens Dynamiques Linq et PredicateBuilder, mais je ne suis pas en mesure de se le représenter comme une solution à mon problème.
Toutes les suggestions seraient appréciées.
Mise à jour
À la suite de la suggestion au sujet de Dynamique Linq, je suis venu avec une très solution de base, à l'aide d'un Opérateur Unique, avec 2 Champs et Critères multiples. Un peu brut pour le moment codé en LinqPad, mais les résultats sont exactement ce que je voulais;
enum Operator
{
Equals = 1,
}
class Condition
{
public string Field { get; set; }
public Operator Operator { get; set;}
public string Value { get; set;}
}
void Main()
{
var conditions = new List<Condition>();
conditions.Add(new Condition {
Field = "Email",
Operator = Operator.Equals,
Value = "[email protected]"
});
conditions.Add(new Condition {
Field = "Email",
Operator = Operator.Equals,
Value = "[email protected]"
});
conditions.Add(new Condition {
Field = "Field1",
Operator = Operator.Equals,
Value = "Chris"
});
var statusConditions = "Status = 1";
var emailConditions = from c in conditions where c.Field == "Email" select c;
var field1Conditions = from c in conditions where c.Field == "Field1" select c;
var emailConditionsFormatted = from c in emailConditions select string.Format("Email=\"{0}\"", c.Value);
var field1ConditionsFormatted = from c in field1Conditions select string.Format("Field1=\"{0}\"", c.Value);
string[] conditionsArray = emailConditionsFormatted.ToArray();
var emailConditionsJoined = string.Join("||", conditionsArray);
Console.WriteLine(String.Format("Formatted Condition For Email: {0}",emailConditionsJoined));
conditionsArray = field1ConditionsFormatted.ToArray();
var field1ConditionsJoined = string.Join("||", conditionsArray);
Console.WriteLine(String.Format("Formatted Condition For Field1: {0}",field1ConditionsJoined));
IQueryable results = ContactView.Where(statusConditions);
if (emailConditions != null)
{
results = results.Where(emailConditionsJoined);
}
if (field1Conditions != null)
{
results = results.Where(field1ConditionsJoined);
}
results = results.Select("id");
foreach (int id in results)
{
Console.WriteLine(id.ToString());
}
}
Avec une instruction SQL générée;
-- Region Parameters
DECLARE @p0 VarChar(1000) = 'Chris'
DECLARE @p1 VarChar(1000) = '[email protected]'
DECLARE @p2 VarChar(1000) = '[email protected]'
DECLARE @p3 Int = 1
-- EndRegion
SELECT [t0].[id]
FROM [Contacts].[ContactView] AS [t0]
WHERE ([t0].[field1] = @p0) AND (([t0].[email] = @p1) OR ([t0].[email] = @p2)) AND ([t0].[status] = @p3)
Et De Sortie De La Console:
Formatted Condition For Email: Email="[email protected]"||Email="[email protected]"
Formatted Condition For Field1: Field1="Chris"
Juste besoin de nettoyer cette et ajouter les autres Opérateurs et il est à la recherche de bonnes.
Si quelqu'un a des commentaires sur cette mesure, toute entrée serait appréciée
OriginalL'auteur ChrisBint | 2011-06-23
Vous devez vous connecter pour publier un commentaire.
Je pense que la Dynamique LINQ sera l'une de l'option. DLINQ vous permet de spécifier la partie de la requête LINQ "chaîne" et DLINQ compile ensuite cette chaîne à l'Expression de l'arbre, de sorte que l'être transmis à la sous-jacentes LINQ fournisseur. Votre besoin est aussi le même que je.e vous avez besoin pour créer des arbres d'Expression au moment de l'exécution.
Je vous suggère de faire de la propriété
Operator
dansFieldCriteria
comme unEnum
qui représentent toutes les opérations requises (d'égal à égal, moins, etc). Ensuite, vous devez écrire une fonction qui prend une liste deFieldCriteria
et le retour d'une "expression" chaîne de caractères qui peuvent ensuite être introduits dans DLINQ pour obtenir l'expression de l'arbre.Vous avez raison à propos de "statique" de l'expression SQL, mais dans la question à l'utilisateur de ne pas savoir à propos de l'expression au moment de la compilation, et donc vous avez besoin de générer des expressions au moment de l'exécution. DLINQ est une façon de le faire à partir de "chaînes" et de l'autre façon est d'utiliser des API d'Expression à la création de la expressions au moment de l'exécution.
OriginalL'auteur Ankur
Le truc avec LINQ serait de construire un
Expression
à partir des données. Comme un exemple, pour illustrer l'exemple illustré:En particulier, notez comment
AndAlso
peuvent être utilisés pour composer les différentes opérations (le même que pour plusieursWhere
, mais en plus simple).non, mais vous aurez à écrire le code qui génère les expressions
comment utiliser DANS l'intérieur de la clause where?
OriginalL'auteur Marc Gravell
Cela peut être fait simplement par Linq où vous joindre d'autres opérateurs de l'objet de requête. Ici est un exemple.
C'est plus simple et court de solution.
OriginalL'auteur indago