2009-06-18 22 views
5

O posiblemente hay una manera mejor.¿Puedo pasar T.Property? Además, ¿ideas para mejorar este método?

Estoy creando un generador de consultas dinámicas para NHibernate, no queremos poner HQL directamente en la aplicación, queremos que sea lo más independiente de ORM posible. Parece que este momento:

public override IEnumerable<T> SelectQuery(Dictionary<string, string> dictionary) 
    { 
     string t = Convert.ToString(typeof (T).Name); 
     string criteria = string.Empty; 
     foreach (KeyValuePair<string, string> item in dictionary) 
     { 
      if (criteria != string.Empty) 
        criteria += " and "; 


      criteria += item.Key + " = '" + item.Value + "'"; 
     } 

     string query = " from " + t; 

     if (criteria != string.Empty) 
      query += " where " + criteria; 

     return FindByHql(query); 
    } 

bien, grande, sin embargo .... hay dos cosas aquí que plantean un problema:

  1. Esta consulta sólo mangos "y" mi inicial el pensamiento es aprobar es construir un método para construir dinámicamente el diccionario que toma el nombre de la propiedad, el valor y un operador "y" o "o" y crea el diccionario junto con una serie de operadores. ¿Eso suena como lo correcto para hacer?

  2. Ok, entonces, esto funciona EXCELENTE, sin embargo, cuando hay un número entero falla debido a las comillas simples. Lo que creo que sería la MEJOR manera es hacer que el diccionario acepte <T.Property, string> y luego reflexionar en T.Property para encontrar el tipo de datos y comportarse de acuerdo con esto. ¿Estoy complicando esto?

Gracias.

Respuesta

3

¿Qué tal algo así?

Donde tiene una enumeración para la operación. En lugar de pasar una cadena para el diccionario, pasa un tipo de QueryObject que tiene el tipo del valor y una operación para el valor. Puedes ver abajo

public enum Operation 
{ 
    And, 
    Or 
} 

public class QueryObject 
{ 
    public string Value { get; set; } 
    public Type Type { get; set; } 
    public Operation Operation { get; set; } 
} 

public override IEnumerable<T> SelectQuery(Dictionary<string, QueryObject> dictionary) 
{ 
    string t = Convert.ToString(typeof(T).Name); 
    string criteria = string.Empty; 
    foreach (KeyValuePair<string, QueryObject> item in dictionary) 
    { 
     if (!string.IsNullOrEmpty(criteria)) 
     { 
      switch (item.Value.Operation) 
      { 
       case Operation.And: 
        criteria += " and "; 
        break; 
       case Operation.Or: 
        criteria += " or "; 
        break; 
       default: 
        break; 
      } 
     } 

     if (item.Value.Type == typeof(int)) 
     { 
      criteria += item.Key + " = " + item.Value + " ";  
     } 
     else 
     { 
      criteria += item.Key + " = '" + item.Value + "'"; 
     } 
    } 

    string query = " from " + t; 

    if (criteria != string.Empty) 
     query += " where " + criteria; 

    return FindByHql(query); 
} 
+0

He utilizado este excepto que acabó con el Diccionario todos juntos y acaba de agregar "propiedad" como cadena a la clase QueryObject. ¡Gracias! –

1

Yo sugeriría posiblemente creando una clase que tiene todas las propiedades que necesita:

Name, 
Value, 
Type, 
JoinType (possibly an enum with Or/And) 

a continuación, tienen su método de tomar una colección de este tipo en lugar de un diccionario. De esta forma, puede verificar fácilmente si necesita hacer y/o, además de verificar si necesita cotizaciones ...

1

Mi pensamiento inicial es que crear algo como esto no es demasiado sensato. Está escribiendo código que genera HQL. Que a su vez pasa a nhibernate que genera SQL.

Sugeriría echar un vistazo a NHibernate criteria consultas. En primer lugar, como una forma más fácil de construir dinámicamente una consulta de NHibernate. Pero también para darle una idea de cuán compleja es la evolución de su propio generador dinámico de consultas.

Dicho eso. Si lo hiciera, probablemente usaría NHibernate Criteria como base para cualquier tipo de generador dinámico de consultas. No hay ninguna razón por la cual no podría generar una consulta para ser utilizada por otro ORM.

Una solución más general al problema es abstraer su acceso a los datos de modo que si desea cambiar el ORM, solo necesita cambiar el código detrás de su abstracción. Esto es más trabajo, por supuesto, pero no estoy convencido de que mantener el código de acceso a datos ORM independiente es algo que es particularmente importante.

+0

consultas de criterios es una buena manera de hacerlo, pero me quedé con mi configuración actual en el espíritu de "conseguir s ** t hecho" –

0

Bien, una alternativa a lo que estás haciendo es pasar una Expresión> en lugar del diccionario y luego analizar la expresión de Linq para lo que quieras. Una pequeña sugerencia que me gustaría hacer es utilizar una consulta Criteria en lugar de HQL. Por supuesto, analizar la expresión de Linq es probablemente mucho más complejo que lo que tienes aquí.

Es posible que pueda procesar el diccionario y obtener un gran HQL, pero me duele la cabeza pensar en hacerlo de esa manera. Las consultas sobre criterios parecen diseñadas para este tipo de cosas.

Cuestiones relacionadas