Pregunta

No estoy seguro de si esto es posible o si estoy expresando correctamente lo que estoy buscando, pero tengo el siguiente fragmento de código en mi biblioteca repetidamente y me gustaría practicar algo de DRY.Tengo un conjunto de tablas de SQL Server que estoy consultando en función de un campo de búsqueda simple proporcionado por el usuario en Google.Estoy usando LINQ para redactar la consulta final en función de lo que hay en la cadena de búsqueda.Estoy buscando una manera de usar genéricos y pasar funciones lambda para crear una rutina reutilizable a partir de esto:

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));
        }
    }
}

Esperaba crear un método genérico con firma que se parezca a:

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

Estoy usando la misma estrategia de búsqueda en todas mis tablas, por lo que lo único que realmente difiere de un uso a otro es MyTable y MyTableEntity buscados y el FieldName buscado.¿Esto tiene sentido?¿Hay alguna manera con LINQ de pasar dinámicamente el nombre del campo a consultar en la cláusula dónde?¿O puedo pasar esto como un predicado lambda?

e => e.FieldName.Contains(queryTerm)

Me doy cuenta de que hay un millón y medio de formas de hacer esto en SQL, probablemente más fáciles, pero me encantaría mantener todo en la familia LINQ para esta.Además, creo que los genéricos deberían ser útiles para un problema como este.¿Algunas ideas?

¿Fue útil?

Solución

Parece que estás buscando Dynamic Linq.Echar un vistazo aquí.Esto le permite pasar cadenas como argumentos a los métodos de consulta, como:

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

Editar:Otro conjunto de publicaciones sobre este tema, utilizando el soporte dinámico de C# 4: Parte 1 y Parte 2.

Otros consejos

Lo que parece es que básicamente quieres un generador de predicados condicionales.

Espero que puedas convertir esto en algo que estés buscando, ¡buena suerte!

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

Quizás quieras mirar árboles de expresión:

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);

Hace poco tuve que hacer lo mismo.Necesitará Linq dinámico aquí es una forma de mantener esto fuertemente tipado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top