2008-09-24 14 views
17

No estoy seguro si esto es posible o si estoy expresando correctamente lo que estoy buscando, pero tengo la siguiente pieza de código en mi biblioteca repetidamente y me gustaría practicar DRY. Tengo un conjunto de tablas de SQL Server que estoy consultando en base a un simple campo de búsqueda proporcionado por el usuario como 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 utilizar los genéricos y aprobada en las funciones lambda para crear una rutina reutilizable de esto:Genérico predicado de consulta LINQ?

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

Tenía la esperanza de crear un método genérico con la firma que se ve algo como:

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 del uso es MyTable & MyTableEntity buscado y FieldName buscado. ¿Esto tiene sentido? ¿Hay alguna manera con LINQ para pasar dinámicamente el nombre del campo para consultar en la cláusula where? ¿O puedo pasar esto como un predicado lambda?

e => e.FieldName.Contains(queryTerm) 

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

+0

La misma pregunta que para la cláusula Select: http://stackoverflow.com/questions/10376947/how-can-i-construct-and-save-to-a-db-for-later-use-a-semi- arbitrario-lambda-expre –

Respuesta

15

Parece que usted está buscando dinámico LINQ. Eche un vistazo here. Esto le permite pasar las cadenas como argumentos a los métodos de consulta, como:

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

Editar: Otra serie de mensajes sobre este tema, usando C# soporte dinámico de 4: Part 1 y Part 2.

+0

¡Gracias! Muy bien, necesito revisar todas las publicaciones del blog de ScottGu sobre este tema ... – Codewerks

+0

Desafortunadamente, solo encontré el - Pensé que tenía una serie, pero creo que estaba equivocado. Sin embargo, hay otras fuentes de información. –

+0

disculpa por hacer una pregunta aquí. ¿Cuál es el predicado y cómo se relaciona con linq? – Thomas

5

Es posible que desee mirar a los á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); 
+0

Creo que la respuesta de Dynamic LINQ es lo que voy a hacer, pero gracias por esto, también intentaré trabajar en esto mañana. – Codewerks

0

recientemente he tenido que hacer esto mismo. Necesitará Dynamic Linqhere, es una manera de mantener esto fuertemente tipado.