Recherche par arbre d'expression en utilisant contient

c# contains expression-trees foreign-keys

Question

ÉDITÉ:

J'essaie de créer une requête en utilisant des arbres d'expression afin d'obtenir un résultat simple, mais je n'ai pas été en mesure de le comprendre.

J'ai des entités d'EF. Entity PointOfSale, qui possède des attributs tels que: Emplacement (qui est un enfant de la région) TypeOfClient ImportanceOfPOS QuantityOfSales.

Ensuite, j'ai un filtre de classe, qui a une liste de régions, une liste de TypesOfClients, une Dist of ImportanceOfPOS et une valeur minimale et maximale pour la quantité de ventes.

Les classes sont définies ci-dessous:

Contexte d'entités = nouvelles entités ();

class PointOfSale 
{
    int p_id;
    Location l;
    QuantityOfSales q;
    TypeOfCliente t;
    ImportanceOfClient i;
    int l_id_fk;
    int t_id_fk;
    int i_id_fk;
}

class Location
{
    int id;
    int region_id_fk;
}

class Region
{
     int id;
     string value;
}

class ValuesForQuantity
{
    int p_id; // ---> Equal to the POS_id
    int? min_value;
    int? max_value;
}

class QuantityOfSales
{
     int id;
     int value;
}

class TypeOfCliente
{
    int id;
    string value;
}

class ImportanceOfClient;
{
    int id;
    string value;
}


class Filter
{
     List<Region> rs;
     ValuesForQuantity v;
     List<ImportanceOfClient> is;
     List<TypeOfClient> ts;
}

Gardez à l'esprit que tous les champs sont facultatifs: je peux ou non avoir des régions, je peux ou non avoir TypeOfClient. De plus, dans ValueForQuantities, je n’aurai peut-être qu’un seul des champs choisis (maximum ou minimum).

J'essaie de construire une version dynamique de ceci:

var query = 
    from p in context.PointsOfSale
    where p.i exists in filter.is  &&
          p.t exists in filter.ts  &&
          p.l in (from l1 in context.Locations where l1 in filter.rs select r) &&
          p.t in (from q in context.Quantities where q.value < filter.v.max_value && q.value > filter.v.max_value)
    select p;

Ce qui va générer un code comme celui-ci:

(p.i.id == filter.i[0] OR p.i.id == filter.i[1] OR p.i.id == filter.i[2])
AND
(p.t.id == filter.t[0] OR p.t.id == filter.t[1])
AND
p.l in (select id from Region r where (r.id == filter.r[0] OR r.id == filter.r[1])
AND
p.q.value < filter.v.max
AND
p.q.value > filter.v.min

Mon arbre d'expression jusqu'à présent est la suivante:

IQueryable<Points_of_sale> queryableDataPOS = context.Points_of_sale.AsQueryable<Points_of_sale>();
ParameterExpression pePOS = Expression.Parameter(typeof(Points_of_sale), "point_of_sale");
ParameterExpression peLocation = Expression.Parameter(typeof(Location), "location");
        List<Expression> expressions = new List<Expression>();

if (showRegion)
        {
            List<Location> ls = getAllLocations(regionList);
            List<Expression> choiceExpressions = new List<Expression>();
            foreach (Location l in ls)
            {
                Expression left = Expression.Property(pePOS, typeof(Points_of_sale).GetProperty("location_id_fk"));
                left = Expression.Convert(left, t.location_id.GetType());
                Expression right = Expression.Constant(t.territory_id);

                Expression expression = Expression.Equal(left, right);
                choiceExpressions.Add(expression);
            }
            if (choiceExpressions.Count > 0)
            {
                Expression totalChoiceExpression = choiceExpressions[0];
                for (int i = 1; i < choiceExpressions.Count; i++)
                {
                    totalChoiceExpression = Expression.Or(totalChoiceExpression, choiceExpressions[i]);
                }
                expressions.Add(totalChoiceExpression);
            }
        }

if (showTypeOfClient)
        {
            List<Expression> choiceExpressions = new List<Expression>();
            foreach (TypeOfClient choice in clients)
            {
                Expression left = Expression.Property(pePOS, typeof(Points_of_sale).GetProperty("type_of_client_id_fk"));
                left = Expression.Convert(left, choice.type_of_client.GetType());
                Expression right = Expression.Constant(choice.type_of_client_id);
                Expression expression = Expression.Equal(left, right);
                choiceExpressions.Add(expression);
            }
            if (choiceExpressions.Count > 0)
            {
                Expression totalChoiceExpression = choiceExpressions[0];
                for (int i = 1; i < choiceExpressions.Count; i++)
                {
                    totalChoiceExpression = Expression.Or(totalChoiceExpression, choiceExpressions[i]);
                }
                expressions.Add(totalChoiceExpression);
            }
        }

if (showImportanceOfClient)
        {
            List<Expression> choiceExpressions = new List<Expression>();
            foreach (ImportanceOfClient choice in importanceOfClients)
            {
                Expression left = Expression.Property(pePOS, typeof(Points_of_sale).GetProperty("importance_of_client_id_fk"));
                left = Expression.Convert(left, choice.importance_of_client_id.GetType());
                Expression right = Expression.Constant(choice.importance_of_client_id);
                Expression expression = Expression.Equal(left, right);
                choiceExpressions.Add(expression);
            }
            if (choiceExpressions.Count > 0)
            {
                Expression totalChoiceExpression = choiceExpressions[0];
                for (int i = 1; i < choiceExpressions.Count; i++)
                {
                    totalChoiceExpression = Expression.Or(totalChoiceExpression, choiceExpressions[i]);
                }
                expressions.Add(totalChoiceExpression);
            }
        }

if (showQuantityOfSales)
{
    // I have no idea how to build this one
}

Expression totalQuery = expressions[0];

// Make the && between all expressions
for (int i = 1; i < expressions.Count; i++)
{
    totalQuery = Expression.And(totalQuery, expressions[i]);
}

MethodCallExpression whereCallExpression = Expression.Call(
            typeof(Queryable),
            "Where",
            new Type[] { queryableDataPOS.ElementType },
            queryableDataPOS.Expression,
            Expression.Lambda<Func<Points_of_sale, bool>>(totalQuery, new ParameterExpression[] { pePOS }));

IQueryable<Points_of_sale> results = queryableDataPOS.Provider.CreateQuery<Points_of_sale>(whereCallExpression);

Donc, 2 questions:

1 - Comment puis-je construire la partie région sans la méthode qui renvoie tous les emplacements. 2 - Comment puis-je créer la branche d'arbre d'expression pour la partie Quantité?

Merci beaucoup et j'espère que c'est maintenant clair :)

Réponse populaire

Commencez par créer une expression LambdaExpression à partir de votre expression "sub". Construisez ensuite l'appel "Contient" (en fait, c'est un appel à Queryable.Any):

var anyExpression = Expression.Call("Queryable.Any", sequence, lambda);

Vous construisez cette expression:

Queryable.Any(sequence, x => x > 5);

Edit: Il semble que vous n’ayez pas besoin de créer un arbre d’expression. Et ça:

var query = context.P_List;

if(filter.zs != null && filter.zs.Count != 0)
 query = query.Where(p => filter.zs.Contains<int>(p.z));

if(filter.ys != null && filter.ys.Count != 0)
 query = query.Where(p => filter.ys.Contains<int>(p.y));

if(filter.as != null && filter.as.Count != 0)
 query = query.Where(p => (from ac in context.a_child where filter.as.Contains(ac) select a).Contains(p.a_child));

//and the same for v2...

var list = query.ToList(); //execute the SQL

J'espère que ça marche.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow