2009-08-10 9 views
6

Solo quería compartir esta clase de Consulta y opinar sobre ella. La clase Query ayuda a ejecutar consultas en una conexión db. No he incluido la implementación, es mucho para publicar. He aquí un ejemplo de llamada, obtendrá la idea:Mi clase de consulta. ¿Su opinión?

OrdersDataTable table = 
    new Query(connection) 
    .Table("Orders") 
    .Fields("OrderID,CustomerID,Description,Amount") 
    .GreaterThan("OrderID", 1000) 
    .OrderBy("OrderID") 
    .Execute<OrdersDataTable>(); 

Aquí está la razones que me gusta la clase:

  • No hay necesidad de escribir el código ADO.NET de comandos. Llamar a esta clase ocupa menos líneas que el equivalente de ADO.NET.
  • Cada función de miembro lo devuelve para que varias llamadas se puedan encadenar juntas. No estoy seguro de si hay un nombre para este patrón. ¿Tú sabes?
  • Maneja los dialectos MySql, OleDb y SqlServer.
  • Me parece más legible que el equivalente de ADO.NET.
  • El orden de las llamadas es irrelevante. Todos los parámetros se almacenan en búfer en colecciones internas y se leen cuando se ejecuta Execute.
  • Mi escenario me obliga a comunicarme con múltiples productos de bases de datos, por lo que me gustaría escribir la consulta una vez de forma genérica y solo pasar la conexión dada. Sería un gran problema aprovechar las funciones específicas de DB, como los procesos almacenados.

Tengo un DAL que utiliza esta clase internamente. La IU realizaría una llamada al DAL, pasaría unos pocos parámetros de consulta y se devolvería la DataTable. La clase realmente ayudó a reducir la implementación de DAL de LOC y la hizo más legible.

Aquí está un ejemplo de llamada DAL:

OrdersDataTable orders = Orders.GetByOrderId(1) 

Y la impl:

public static OrdersDataTable GetByOrderId(int id) 
{ 
    return 
     new Query(connection) 
     .Table("Orders") 
     .Fields("OrderID,CustomerID,Description,Amount") 
     .Equals("OrderID", id) 
     .Execute<OrdersDataTable>(); 
} 

Gracias!

Editar: Gracias a todos por la gran retroalimentación. Muchos de ustedes sugirieron LinqToSql. No elegí Linq porque Microsoft actualmente solo admite el servidor Sql. Necesito consultar las tablas Jet, MySql y Sql Server.

Alguien preguntó cómo se construyen las cláusulas AND y OR. Aquí un ejemplo de cada

//and example 
    public static OrdersDataTable GetByOrderIdAndCustomerId(int orderId, int customerId) 
    { 
     return 
      new Query(connection) 
      .Table("Orders") 
      .Fields("OrderID,CustomerID,Description,Amount") 
      .Equals("OrderID", orderId) 
      .Equals("CustomerID", customerId) 
      .Execute<OrdersDataTable>(); 
    } 

//or example 
    public static OrdersDataTable GetByOrderIdOrCustomerId(int orderId, int customerId) 
    { 
     return 
      new Query(connection) 
      .Table("Orders") 
      .Fields("OrderID,CustomerID,Description,Amount") 
      .OrBegin 
      .Equals("OrderID", orderId) 
      .Equals("CustomerID", customerId) 
      .OrEnd 
      .Execute<OrdersDataTable>(); 
    } 
+4

Por curiosidad ... Si está usando C#, ¿qué hay de malo con LINQ? –

+0

¡Me gusta! Sería bueno si eres como yo y atrapado en 2.0. –

+0

Me gusta. Debe saber que, si prefiere el estilo de puntos de la interfaz fluida, puede hacerlo también con Linq. –

Respuesta

3

Parece que usted ha escrito un muy bonito y pequeño ORM (objeto del asignador relacional) con una implementación del repositorio (o cerca de) patrón. También aprovechó el patrón de diseño llamado Interfaces fluidas, que es lo que le permite hacer .Table. Campos en cascada entre sí.

Todos los 3 de estos patrones son muy buenos para ser incluidos en el diseño de sistemas de software modernos ya que notan que reducen en gran medida el LOC, mejoran el mantenimiento y mejoran enormemente la capacidad de prueba. También me gusta que haya construido su funcionalidad para poder devolver objetos fuertemente tipados utilizando genéricos correctamente.

Editar sección: La única área posible que pude ver para mejorar sería cambiar el hecho de que cada llamada es una nueva consulta y quizás cambiar su código para usar un marco de inyección de dependencia que inyectará el proveedor correcto y cuando el objeto se llama que iniciará una transacción de base de datos para la consulta.Si su código ya lo hace internamente en la clase Query que podría llamarse "inyección de dependencia de los pobres" o al menos es muy similar (dependiendo de su implementación) que si ya está trabajando para usted y no tiene la intención de crecer realmente con sus tipos de soporte de base de datos, la DI del pobre debería estar bien. Simplemente no soy un fanático de la palabra clave nueva en ningún otro uso ya que generalmente causa altos niveles de acoplamiento de código que un marco DI alivia (o es por el método que se esconde con una mala decisión de diseño malo).

En respuesta a la respuesta de Mark, por lo general no soy un fan de generación de código que siempre parece ser un punto de fallo, sin embargo él tiene un muy buen punto para reducir la cantidad de cuerdas mágicas implicadas. En vez de ello optar por utilizar el operador lambda y expresiones de manejar esto, sin embargo, por lo que podría lograr esto:

public static OrdersDataTable GetByOrderId(int id) 
{ 
    return 
     new Query(connection) 
     .Table(x => Inflector.Pluralize(x.GetType()) 
     .Fields(x=> { x.OrderID, x.CustomerID, x.Description, x.Amount }) 
     .Equals(x=>x.OrderID, id) 
     .Execute<OrdersDataTable>(); 
} 

Esto eliminará todos los problemas de la cadena de refactorización de magia lo que permite aprovechar de Microsoft integrado en las herramientas de refactorización mucho más fácil o Resharper (por supuesto, el reafilamiento puede encontrar cadenas mágicas durante la refactorización).

Inflector es una biblioteca gratuita (no recuerdo si es OSS o no) que incluye funcionalidad para tratar con texto, el método Pluralize tomará una palabra y lo hará ... plural si no puede adivinar. Donde esto es útil es cuando tienes como Historia donde no puedes ir a GetType() + "s" ya que Storys no es correcto y el Inflector te devolverá correctamente "Historias".

+0

Eso es bastante interesante, no han explorado las expresiones de Lamda. Pero probablemente todavía use ORM autogenerados y Business Objects que usan procedimientos almacenados en esta etapa. –

+0

Revisaré el reflector. Me gusta el uso de Lamdas. ¡Gracias! – Steve

+0

Si no encontró la URL ya es: http://andrewpeters.net/inflectornet/ –

1

Normalmente trato de evitar estas formas funcionales de hacer las cosas. A veces puede ser confuso rastrear problemas cuando surgen.

Solo usaría LINQ y realizaría la misma tarea con un código más legible.

0

Aunque estoy de acuerdo en que Linq está diseñado para hacer esto, no hay razón para no crear su propia arquitectura si funciona para sus requisitos.

Iría un poco más allá y usaría la generación de código para crear Tipos enumerados u otro objeto basado en el entitulado para reducir la necesidad de texto literal. (y reduce los errores tipográficos)

+1

Si tiene el tiempo y el dinero para implementar su arquitectura cuando una existente hará lo mismo, entonces seguro. Pero la mayoría de los proyectos en los que he trabajado, este no ha sido el caso. – mkchandler

+0

Estoy de acuerdo contigo. Me gustaría dedicar mi tiempo a encapsular Linq u otra tecnología (utilizo procedimientos almacenados y genero ORM/Business Objects) para hacer las cosas más fáciles y más rápidas en un nivel superior. Esto potencialmente no resuelve problemas o acelera el desarrollo. –

0

Es un ejercicio divertido y su código parece ser bastante legible y conciso. En un entorno de producción, probablemente me mantendría alejado de reinventar la rueda a menos que hubiera una necesidad seria de hacerlo. Mi tiempo, y el tuyo, sería mejor gastar la creación de valor en la aplicación, sin agregar funcionalidad al ORM personalizado que podemos obtener "gratis" en otros paquetes probados en batalla como LINQ y NHibernate.

Cuestiones relacionadas