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

发布于 2024-08-23 01:08:09 字数 876 浏览 5 评论 0原文

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

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

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

(顺便说一句,对于为什么我不选择一个引擎这一不可避免的问题。我喜欢让用户选择最适合他们的引擎。SQL Compact 允许复制到完整的 SQL Server 实例。SQLite 是可移植的,并且我可以想象这样一种情况:一家公司想要添加一个 MySQL 插件,以便他们可以轻松地存储和整理应用程序的性能数据。应该必须依赖于我的底层数据库引擎的实现细节才是荒谬的。)

I work on a C# client application (SlimTune Profiler) that uses relational (and potentially embedded) database engines as its backing store. The current version already has to deal with SQLite and SQL Server Compact, and I'd like to experiment with support for other systems like MySQL, Firebird, and so on. Worse still, I'd like it to support plugins for any other backing data store -- and not necessarily ones that are SQL based, ideally. Topping off the cake, the frontend itself supports plugins, so I have an unknown many-to-many mapping between querying code and engines handling the queries.

Right now, queries are basically handled via raw SQL code. I've already run into trouble making complex SELECTs work in a portable way. The problem can only get worse over time, and that doesn't even consider the idea of supporting non-SQL data. So then, what is the best way to query wildly disparate engines in a sane way?

I've considered something based on LINQ, possibly the DbLinq project. Another option is object persistence frameworks, Subsonic for example. But I'm not too sure what's out there, what the limitations are, or if I'm just hoping for too much.

(An aside, for the inevitable question of why I don't settle on one engine. I like giving the user a choice of the engine that works best for them. SQL Compact allows replication to a full SQL Server instance. SQLite is portable and supports in-memory databases. I can imagine a situation where a company wants to drop in a MySQL plugin so that they can easily store and collate an application's performance data over the course of time. Last and most importantly, I find the idea that I should have to be dependent on the implementation details of my underlying database engine to be absurd.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

内心激荡 2024-08-30 01:08:09

最好的选择是使用一个接口来进行所有数据库访问。然后,对于您想要支持的每种数据库类型,执行该数据库的接口的实现。这就是我过去必须为项目做的事情。

许多数据库系统和存储工具的问题在于它们旨在解决不同的问题。您甚至可能不想将数据存储在 SQL 数据库中,而是将其作为文件存储在 Web 应用程序的 App_Data 文件夹中。使用接口方法,您可以很容易地做到这一点。

通常没有一种解决方案能够很好地适合所有数据库和存储解决方案,甚至无法很好地适合其中的一些解决方案。如果你找到一个声称确实如此的人,我仍然不会相信它。当您的某个数据库出现问题时,您挖掘自己的对象比挖掘他们的对象要容易得多。

Your best bet is to use an interface for all of your database access. Then for each database type you want to support to do the implementation of the interface for that database. That is what I've had to do for projects in the past.

The problem with many database systems and storage tools is that they aim to solve different problems. You might not even want to store your data in a SQL database but instead store it as files in the App_Data folder of a web application. With an interface method you could do that quite easily.

There generally isn't a solution that fits all database and storage solutions well or even a few of them well. If you find one that claims it does I still wouldn't trust it. When you have a problem with one of the databases it's going to be much easier for you to dig through your objects than it will be to go dig through theirs.

执手闯天涯 2024-08-30 01:08:09

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

Use an object-relational mapper. This will provide a high level of abstraction away from the different database engines, and won't impose (many) limitations on the kind of queries you can run. Many ORMs also include LINQ support. There are numerous questions on SO providing recommendations and comparisons (e.g. What is your favorite ORM for .NET? appears to be the most recent and has links to several others).

泅渡 2024-08-30 01:08:09

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

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

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

I would recommend the repository pattern. You can create a class that encapsulates all the actions that you need the database for, and then create a different implementation for each database type you want to support. In many cases, for relationional data stores, you can use the ADO.NET abstractions (IDbConnection, IDataReader, IDataAdapter, etc) and create a single generic repository, and only write specific implementations for the database types that do not provide an ADO.NET driver.

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

I don't actually know what you are storing, so you'd have to adapt this for your actual needs. I'm also guessing this would require some heavy refactoring as you might have sql statements littered throughout your code. And pulling these out and encapsulating them might not be feasible. But IMO, that's the best way to achieve what you want to do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文