Question

Je ne sais pas si cela est possible ou si j'exprime correctement ce que je cherche, mais j'ai le code suivant dans ma bibliothèque à plusieurs reprises et j'aimerais pratiquer un peu à la DRY. J'ai un ensemble de tables SQL Server que j'interroge en fonction d'un simple champ de recherche fourni par l'utilisateur, tel que Google. J'utilise LINQ pour composer la requête finale en fonction du contenu de la chaîne de recherche. Je cherche un moyen d'utiliser des génériques et de passer des fonctions lambda pour créer une routine réutilisable à partir de ceci:

string[] arrayOfQueryTerms = getsTheArray();

var somequery = from q in dataContext.MyTable
                select q;

if (arrayOfQueryTerms.Length == 1)
{
    somequery = somequery.Where<MyTableEntity>(
        e => e.FieldName.StartsWith(arrayOfQueryTerms[0]));
}
else
{
    foreach(string queryTerm in arrayOfQueryTerms)
    {
        if (!String.IsNullOrEmpty(queryTerm))
        {
            somequery = somequery 
                        .Where<MyTableEntity>(
                            e => e.FieldName.Contains(queryTerm));
        }
    }
}

J'espérais créer une méthode générique avec une signature ressemblant à quelque chose comme:

private IQueryable<T> getQuery(
    T MyTableEntity, string[] arrayOfQueryTerms, Func<T, bool> predicate)

J'utilise la même stratégie de recherche pour toutes mes tables. La seule chose qui diffère vraiment d'un usage à l'autre est la table MyTable & amp; MyTableEntity recherché et le FieldName recherché. Est-ce que ça a du sens? Existe-t-il un moyen avec LINQ de transmettre dynamiquement le nom du champ à interroger dans la clause where? Ou puis-je transmettre ceci en tant que prédicat lambda?

e => e.FieldName.Contains(queryTerm)

Je me rends compte qu'il existe un million et demi de façons de faire cela en SQL, probablement plus facile, mais j'aimerais tout garder dans la famille LINQ pour celle-ci. De plus, j'estime que les génériques devraient être pratiques pour un problème comme celui-ci. Des idées?

Était-ce utile?

La solution

On dirait que vous recherchez Dynamic Linq. Jetez un coup d'oeil ici . Cela vous permet de passer des chaînes en tant qu'arguments aux méthodes de requête, comme:

var query = dataSource.Where("CategoryID == 2 && UnitPrice > 3")
                      .OrderBy("SupplierID");

Édition: un autre ensemble de publications sur ce sujet, utilisant le support dynamique de C # 4: Partie 1 et Partie 2 .

Autres conseils

Ce que cela ressemble est que vous voulez essentiellement un constructeur de prédicat conditionnel.

J'espère que vous pourrez transformer cela en quelque chose que vous recherchez, bonne chance!

http://www.albahari.com/nutshell/predicatebuilder.aspx

Vous voudrez peut-être examiner les arbres d'expression:

IQueryable<T> getQuery<T>(T myTableEntity, string[] arrayOfQueryTerms, Expression<Func<T, bool>> predicate)
 { var fieldOrProperty = getMemberInfo(predicate);
   /* ... */
 }

MemberInfo getmemberInfo<T>(Expression<Func<T,bool> expr)
 { var memberExpr = expr as MemberExpression;
   if (memberExpr != null) return memberExpr.Member;
   throw new ArgumentException();
 }

var q = getQuery<FooTable>(foo, new[]{"Bar","Baz"}, x=>x.FieldName);

J'ai récemment dû faire la même chose. Vous aurez besoin de Dynamic Linq < un href = "http://talesfromthebleedingedge.blogspot.com/2008/10/linq-to-entities-dynamic-linq-to.html" rel = "nofollow noreferrer"> ici est un moyen de le conserver fortement typé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top