我一直在设计一个数据库访问层,它允许我们在程序中支持多个数据库。最后,我们程序的用户应该能够从一系列数据库系统中选择底层数据库系统。一些小客户可能对MS Access感到满意,其他人更喜欢MySql,其他人更喜欢DB2。那些数据库系统是我现在想要的目标。
鉴于这些要求,我想出了一个抽象类DatabaseConnection。在内部,我使用System.Data.Common.Data.DbConnection类,这已经给了我很大的灵活性。
需要具体实例的东西(例如OleDbCommand而不是DbCommand)隐藏在CreateDbCommand()等抽象方法中。子类(如AccessDbConnection)实现这些并提供具体实例。目前,这导致了这种层次结构(类名缩写为可读性):
DatabaseConnection / | \ AccessConn MySqlConn DB2Conn
但是,有一些特定于底层数据库系统的操作,例如检索所有表名。将抽象方法GetTableNames()放入DatabaseConnection类并让子类覆盖它是错误的。
我想也许我可以创建另一个名为DatabaseTools的抽象基类,在那里声明那些操作,然后在类似于DatabaseConnection类的子类的子类中实现它们。这意味着对于AccessDbConnection,我还有一个类AccessTools等等:
DatabaseConnection DatabaseTools / | \ / | \ AccessConn MySqlConn DB2Conn AccessTools MySqlTools DB2Tools
不知何故,我对这个想法并不感到激动。
您有什么想法来解决这个设计问题?
提前感谢您的时间和答案:)
干杯
基督教
答案 0 :(得分:3)
为什么不实现使用ANSI标准INFORMATION_SCHEMA
视图检索表名的方法,而不是抽象方法,然后在DatabaseConnection
实现中为不符合ANSI标准的提供程序覆盖它?
除此之外,从设计的角度来看,我没有看到抽象方法方法有任何问题。
答案 1 :(得分:1)
由于您没有获得100%OO纯度的分数,请遵循Swingline Rage的建议。你也可以通过重命名类来使它变得纯粹; - )
唯一的问题是,如果使用Interfaces而不是Abstract Classes和继承,则不太可能被烧毁。接口可以相互继承,但您可能不需要它。有点难写,但你可以用同样的方式使用它们。
http://www.codeproject.com/KB/cs/abstractsvsinterfaces.aspx
Interface or an Abstract Class: which one to use?
“基类中的共享代码怎么样?” - 如果使用静态类并调用它们,则可以保留DRY(在OO中使用某些过程技术不是罪过)。上面的堆栈溢出主题中的Q#2看起来很有趣,但我无法保证它。
答案 2 :(得分:1)
在我看来,在单独的层次结构中定义数据库操作是一个更好的主意。 我更愿意将工具封装在具体连接对象中,然后通过单个Factory获取连接。
准确地说,要执行任务以获取所有表名,调用将如下所示:
ConnectionFactory(ACSESS).getConnection().getTools().fetchSchema();