如何设计独立于提供商的 DAL

发布于 2024-07-17 06:16:38 字数 601 浏览 12 评论 0原文

我目前正在开发一个查询生成器应用程序,基本上是一个简单的图形界面,它应该允许不了解 SQL 的用户在数据库上定义各种查询(连接、SELECT、INSERT、UPDATE、DELETE)。 我将使用 .NET 3.5。 我的应用程序应该支持多个数据库,它应该与 MS-SQL Server、MySQL 和 Oracle 一起使用,因此我将不胜感激有关如何设计独立于提供商的 DAL 的相关讲座的任何提示或链接。

用户将选择一个数据库服务器、当前服务器上的数据库、提供连接凭据、选择各种表、定义查询(使用一系列组合框),最后执行查询(如果查询有效)。 当然,在 DAL 中,我确实希望为每个数据库提供者提供方法。 我正在思考一些关于工厂模式的事情。

注意:这是一个简单的学校项目,因此我对结果查询的安全性或性能不感兴趣。

更新:经过更多研究并根据您提供的非常有价值的意见,我决定使用DbProviderFactory。 ORM 会很有趣,但由于我只想要一个查询分析器/构建器,所以我不认为使用它有什么意义。 因此,如果您能给我提供有关如何使用 DbProviderFactory 和相关类的详细教程,我将不胜感激。

I am currently developing a query builder application, basically, a simple graphical interface that should allow users with no knowledge of SQL to define various queries on a database (joins, SELECT, INSERT, UPDATE, DELETE). I will be using .NET 3.5. My application should support multiple databases, it should work with MS-SQL Server, MySQL and Oracle, so I would appreciate any hints or links to relevant lecture on how to design a provider-independent DAL.

The user will select a database server, a database on the current server, provide the connection credentials, choose various tables, define queries (using a series of combo boxes) and finally execute the queries if they are valid. Of course, in the DAL I do want to have methods for each DB provider. I am thinking something on the lines of the factory pattern.

Note: This is a simple school project, so I am not interested in the security or performance of the resulting queries.

UPDATE: After some more research and with the very valuable input that you have provided, I decided to use DbProviderFactory. ORM would be interesting, but since I just want a query analyzer/builder, I don't see the point of using one. So, I would appreciate if you would point me to a detailed tutorial on how to use DbProviderFactory and the associated classes.

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

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

发布评论

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

评论(6

梦明 2024-07-24 06:16:38

我建议使用 System.Data.Common.DbProviderFactories 类来生成通用 ADO.NET 类。

当您找到更多想要支持的数据库 .NET 提供程序时,只需将提供程序 DLL 拖放到应用程序的路径中,然后在 app.configDbProviderFactory 的引用即可代码> 文件。 您可以让用户选择要使用的提供商。

这是一篇关于主题的 MSDN 文章,名为 获取 DbProviderFactory (ADO.NET)

我以前使用过这种方法,并且能够在同一项目中通过较小的配置更改来支持 MSSQL 和 SQLite。

不确定,它是否也适用于查询生成器应用程序......

I recommend using the System.Data.Common.DbProviderFactories class to generate generic ADO.NET classes.

As you find more .NET providers for databases you want to support, simply drop the provider DLL in the app's path and add a reference to the DbProviderFactory of the provider in the app.config file. You can have the user select the provider to use.

Here is an MSDN article on the topic called Obtaining a DbProviderFactory (ADO.NET)

I've used this approach before and been able to support MSSQL and SQLite in the same project with a minor configuration change.

Not sure, if it'll work as well for a query builder app though…

小伙你站住 2024-07-24 06:16:38

我必须说,以可视方式编辑相当复杂的查询非常很麻烦。 而允许用户使用可视化设计器插入/删除数据无疑是搬起石头砸自己的脚。 Management Studio 的缩小版、基本 SQL 知识加上受限服务器用户将做得更好。

如果您仍然倾向于设计这个应用程序,您将需要 NHibernate。 更准确地说,条件查询将完成这项工作,因为它们映射得很好接近你所需要的。

I must say that editing a reasonably complex query visually is very cumbersome. And allowing users to insert/delete data using visual designer is a certain way to shoot yourself in the foot. A sized-down version of Management Studio, knowledge of basic SQL plus restricted server user will do a much better job.

If you're still inclined to design this app, you'll need NHibernate. More precisely, Criteria Queries will do the job, since they map pretty close to what you need.

-黛色若梦 2024-07-24 06:16:38

您可能会感到惊讶,但是使用普通的旧 DataSetDataTable 可以实现非常简单的独立于提供者的 DAL 。

You might be surprised, but a very simple provider-independent DAL can be achieved with plain old DataSet and DataTable.

梦言归人 2024-07-24 06:16:38

我认为 ADO.NET 实体框架(自 .NET 3.5 SP1 起可用)是一个不错的选择,因为它几乎用实体 SQL 语言抽象出了依赖于数据库的 SQL。

I think ADO.NET Entity Framework (available since .NET 3.5 SP1) is a great choice as it pretty much abstracts away database-dependent SQL with its entity SQL language.

耶耶耶 2024-07-24 06:16:38

大多数 ORM(对象关系映射器)都知道如何与各种数据库类型通信。

至于允许用户构建自己的查询:您需要非常小心。 与其说用户可能创建恶意查询(尽管这可能是一个问题),不如说这是意外。 编写一个使用所有可用服务器资源并为数据库创建有效的拒绝服务的查询非常容易。

Most any ORM (Object-Relational Mapper) will know how to talk to a variety of database types.

As for allowing users to build their own queries: you need to be very careful with this. It's not so much that users could create malicious queries (though that can be a problem) as it is accident. It's surprisingly easy to write a query that will use all available server resources and create an effective denial of service for your database.

三生池水覆流年 2024-07-24 06:16:38

我不确定这是否有助于您的追求,但我最近学到并牢记的一件事是让数据模型的唯一标识符实现不直接传播到数据层之外,而是包装在抽象中。 例如,下面是一个包装模型标识符的接口:

public interface IModelIdentifier<T> where T : class 
{
    /// <summary>
    /// A string representation of the domain the model originated from.
    /// </summary>
    string Origin { get; }

    /// <summary>
    /// The model instance identifier for the model object that this 
    /// <see cref="IModelIdentifier{T}"/> refers to.  Typically, this 
    /// is a database key, file name, or some other unique identifier.
    /// <typeparam name="KeyDataType">The expected data type of the 
    /// identifier.</typeparam>
    /// </summary>
    KeyDataType GetKey<KeyDataType>();

    /// <summary>
    /// Performs an equality check on the two model identifiers and 
    /// returns <c>true</c> if they are equal; otherwise <c>false</c> 
    /// is returned.  All implementations must also override the equal operator.
    /// </summary>
    /// <param name="obj">The identifier to compare against.</param>
    /// <returns><c>true</c> if the identifiers are equal; otherwise 
    /// <c>false</c> is returned.</returns>
    bool Equals(IModelIdentifier<T> obj);
}

您的业务逻辑层,过去可能将 int 作为唯一标识符传递(例如,来自数据库表中的标识列) ),现在这样传递:

    public IPerson RetrievePerson(IModelIdentifier<IPerson> personId)
    {
        /// Retrieval logic here...
    }

您的数据层将有一个实现 IModelIdentifier 的类,并使用物理模型的唯一标识符填充其内部数据类型。 这可以使您的业务层免受数据层可能发生的任何更改的影响,例如将 int 键标识符替换为 Guid

I'm not sure if this assists with your quest, but one thing I learned rather recently and took to heart is to have your data model's unique identifier implementation not propagate directly outside of the data layer, but to be wrapped in an abstraction. For instance, here is an interface which wraps a model's identifier:

public interface IModelIdentifier<T> where T : class 
{
    /// <summary>
    /// A string representation of the domain the model originated from.
    /// </summary>
    string Origin { get; }

    /// <summary>
    /// The model instance identifier for the model object that this 
    /// <see cref="IModelIdentifier{T}"/> refers to.  Typically, this 
    /// is a database key, file name, or some other unique identifier.
    /// <typeparam name="KeyDataType">The expected data type of the 
    /// identifier.</typeparam>
    /// </summary>
    KeyDataType GetKey<KeyDataType>();

    /// <summary>
    /// Performs an equality check on the two model identifiers and 
    /// returns <c>true</c> if they are equal; otherwise <c>false</c> 
    /// is returned.  All implementations must also override the equal operator.
    /// </summary>
    /// <param name="obj">The identifier to compare against.</param>
    /// <returns><c>true</c> if the identifiers are equal; otherwise 
    /// <c>false</c> is returned.</returns>
    bool Equals(IModelIdentifier<T> obj);
}

Your business logic layer, which may have in the past passed around ints as unique identifiers (for instance, from a identity column in your database table), is now passed as such:

    public IPerson RetrievePerson(IModelIdentifier<IPerson> personId)
    {
        /// Retrieval logic here...
    }

Your data layer will then have a class which implements IModelIdentifier<Person> and populates its internal data type with the physical model's unique identifier. This insulates your business layer from any changes you may have at the data layer, such as replacing your int key identifiers with Guids.

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