以统一的方式查询不同数据库引擎的最佳方法是什么?

时间:2010-02-24 21:09:04

标签: c# sql database portability

我使用C#客户端应用程序(SlimTune Profiler),它使用关系(和可能嵌入的)数据库引擎作为其后备存储。当前版本已经处理SQLite和SQL Server Compact,我想尝试支持MySQL,Firebird等其他系统。更糟糕的是,我希望它支持任何其他支持数据存储的插件 - 而不一定是基于SQL的插件,理想情况下。蛋糕前端,前端本身支持插件,所以我在查询代码和处理查询的引擎之间有一个未知的多对多映射。

现在,查询基本上是通过原始SQL代码处理的。我已经遇到了麻烦,使复杂的SELECT以可移植的方式工作。问题只会随着时间的推移而变得更糟,甚至不考虑支持非SQL数据的想法。那么,以一种理智的方式查询疯狂的不同引擎的最佳方法是什么?

我考虑过基于LINQ的东西,可能是DbLinq项目。另一种选择是对象持久性框架,例如Subsonic。但是我不太确定那里有什么,有什么限制,或者我只是希望得太多。

(另外,对于为什么我不解决一个引擎的不可避免的问题。我喜欢让用户选择最适合他们的引擎.SQL Compact允许复制到完整的SQL Server实例.SQLite是可移植的,并支持内存数据库。我可以想象一个公司想要放入MySQL插件的情况,以便他们可以随时轻松地存储和整理应用程序的性能数据。最后也是最重要的是,我发现认为我应该依赖我的底层数据库引擎的实现细节是荒谬的。)

3 个答案:

答案 0 :(得分:2)

最好的办法是为所有数据库访问使用接口。然后,为每个要支持的数据库类型执行该数据库的接口。这就是我过去必须为项目做的事情。

许多数据库系统和存储工具的问题在于它们旨在解决不同的问题。您甚至可能不希望将数据存储在SQL数据库中,而是将其作为文件存储在Web应用程序的App_Data文件夹中。使用接口方法,您可以非常轻松地完成此操作。

通常没有一种解决方案可以很好地适应所有数据库和存储解决方案,甚至可以很好地适应其中的一些。如果你找到一个声称它的人,我仍然不相信它。当你对其中一个数据库有问题时,你可以更容易地挖掘你的物体,而不是去挖掘它们。

答案 1 :(得分:1)

使用对象关系映射器。这将提供远离不同数据库引擎的高级抽象,并且不会对您可以运行的查询类型施加(许多)限制。许多ORM还包括LINQ支持。有很多关于SO提出建议和比较的问题(例如What is your favorite ORM for .NET?似乎是最新的,并且与其他几个有关联。)

答案 2 :(得分:0)

我会推荐存储库模式。您可以创建一个类,该类封装了数据库所需的所有操作,然后为要支持的每种数据库类型创建不同的实现。在许多情况下,对于关系数据存储,您可以使用ADO.NET抽象(IDbConnection,IDataReader,IDataAdapter等)并创建单个通用存储库,并仅为不提供ADO.NET的数据库类型编写特定实现驱动程序。

public interface IExecutionResultsRepository
{
  void SaveExecutionResults(string name, ExecutionResults results);
  ExecutionResults GetExecutionResults(int id);
}

我实际上并不知道你要存储什么,所以你必须根据实际需要调整它。我也猜测这需要一些重构,因为你可能在你的代码中散布着sql语句。将它们拉出并封装它们可能并不可行。但是IMO,这是实现你想要做的最好的方式。