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
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
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. –
@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