2010-06-10 13 views
5

He estado diseñando una capa de acceso a la base de datos que nos permite admitir múltiples bases de datos en nuestros programas. Al final, los usuarios de nuestros programas podrán elegir el sistema de base de datos subyacente de una gama de sistemas de bases de datos. Algunos clientes pequeños pueden estar contentos con MS Access, otros prefieren MySql, otros DB2. Esos sistemas db son a los que quiero apuntar por ahora.Pregunta de diseño de capa de base de datos

Dados esos requisitos, he creado una clase abstracta de conexión de base de datos. Internamente, uso System.Data.Common.Data.DbConnection-class, que ya me da bastante flexibilidad.
Las cosas que necesitan instancias concretas (OleDbCommand en lugar de DbCommand, por ejemplo) están ocultas en métodos abstractos como CreateDbCommand(). Las subclases (como AccessDbConnection) implementan esas y proporcionan las instancias concretas. Actualmente que conduce a esta jerarquía (abrevian los nombres de clase para facilitar la lectura):

  DatabaseConnection 
     /  |  \ 
AccessConn  MySqlConn  DB2Conn 

Sin embargo, hay algunas operaciones que son específicos para el sistema de base de datos subyacente, como la recuperación de todos los nombres de tabla. Se siente mal colocar un método abstracto GetTableNames() en la clase DatabaseConnection y hacer que las subclases lo sobrescriban.

Pensé que quizás podía crear otra clase base abstracta llamada DatabaseTools, declarar esas operaciones allí y luego implementarlas en subclases que se asemejan a las subclases de la clase DatabaseConnection. Lo que significa que para un AccessDbConnection, yo también tendría un AccessTools clase, etc, etc:

  DatabaseConnection      DatabaseTools 
     /  |  \     /  |  \ 
AccessConn  MySqlConn  DB2Conn AccessTools MySqlTools DB2Tools 

De alguna manera no estoy realmente encantados con esta idea.

¿Qué ideas tienes para resolver este problema de diseño?

Gracias de antemano por su tiempo y respuestas :)

Saludos

Cristiano

+0

Lo que se preocupa por el diseño? Me parece razonable (a primera vista). Me gustaría incluir alguna forma de garantizar que no se pueda usar un 'AccessTools' con un' MySQLConn', pero eso es lo único que se me ocurre. – ChrisF

+0

Creo que el enfoque del método abstracto está bien. ¿Qué razón más convincente puedes dar para violar la navaja de afeitar de Occam y el principio de KISS y crear una segunda serie de clases donde una hubiera bastado? Utilicé la primera arquitectura que describiste en media docena de proyectos y nunca tuve problemas con ella. Simplemente no se requiere mucho código específico de DB, siempre que se adhiera a SQL estándar. –

+0

@ChrisF: Cuando pienso en una clase DatabaseConnection, simplemente la considero la conexión misma, que me permite crear, abrir y cerrar la conexión. La consulta de todos los nombres de tabla y otras operaciones específicas del sistema db tiene que hacer algo con la conexión (después de todo, operan en ella), pero creo que no deberían estar vinculadas a la conexión demasiado estrecha. – Christian

Respuesta

1

Dado que no obtiene puntos por tener pureza 100% OO, siga los consejos de Swingline Rage. También podría hacerlo puro simplemente cambiando el nombre de la clase ;-)

Lo único es que si usa interfaces en lugar de clases abstractas y herencia, es menos probable que se queme. Las interfaces pueden heredarse unas de otras, pero probablemente no las necesite. Un poco más difícil de escribir, pero puede usarlos de la misma manera.

http://www.codeproject.com/KB/cs/abstractsvsinterfaces.aspx
Interface or an Abstract Class: which one to use?

"¿qué pasa con código compartido en la clase base?" - Puede quedarse DRY si usa clases estáticas y las llama (no es un pecado usar algunas técnicas de procedimiento en OO).Q # 2 en el tema de desbordamiento de pila anterior parece interesante pero no puedo responderlo.

3

En lugar de un método abstracto, por qué no implementar uno que recupera los nombres de tabla utilizando los estándares ANSI-INFORMATION_SCHEMA vistas, y luego simplemente anularlo en una implementación DatabaseConnection para un proveedor que no cumple con ANSI?

Aparte de eso, no veo nada de malo en el enfoque del método abstracto desde el punto de vista del diseño.

1

En mi opinión, la definición de las operaciones de db en una jerarquía separada es una Idea mejor. Preferiría encapsular las herramientas dentro de los objetos de las conexiones de concreto y luego obtener las conexiones a través de una sola fábrica.

Precisamente, para realizar una tarea de conseguir todos los nombres de las tablas, la llamada se verá así:

ConnectionFactory(ACSESS).getConnection().getTools().fetchSchema(); 
Cuestiones relacionadas