如何设计独立提供商DAL(.Net)

时间:2009-04-21 12:42:47

标签: .net data-access-layer query-builder provider-independent

我目前正在开发一个查询构建器应用程序,基本上是一个简单的图形界面,应该允许不了解SQL的用户在数据库上定义各种查询(连接,选择,更新,插入,删除)。我将使用.Net 3.5。我的应用程序应该支持多个数据库,它应该与MS-SQL Server,MySQL和Oracle一起使用,所以我将非常感谢有关如何设计提供者独立DAL 的相关讲座的任何提示或链接。

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

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

更新:经过一些研究,并提供了您提供的非常有价值的信息后,我决定使用DbProviderFactory。 ORM会很有趣但是因为我只想要一个查询分析器/构建器,所以我没有看到使用它的意义。所以,如果你能给我一个关于如何使用DbProviderFactory和相关类的详细教程,我将不胜感激。

6 个答案:

答案 0 :(得分:2)

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

当您发现要支持的数据库的更多.NET提供程序时,只需将提供程序DLL放在应用程序的路径中,并在app.config文件中添加对提供程序的DbProviderFactory的引用。您可以让用户选择要使用的提供程序。

以下是有关该主题的MSDN文章:Obtaining a DbProviderFactory (ADO.NET)

之前我已经使用过这种方法,并且能够在同一个项目中支持MSSQL和SQLite,并进行微小的配置更改。

不确定它是否也适用于查询构建器应用程序......

答案 1 :(得分:0)

我认为ADO.NET实体框架(自.NET 3.5 SP1开始提供)是一个很好的选择,因为它几乎用实体SQL语言抽象出依赖数据库的SQL。

答案 2 :(得分:0)

您可能会感到惊讶,但可以通过以下方式实现非常简单的提供者独立DAL:

普通的 DataSet DataTable

答案 3 :(得分:0)

我必须说,直观地编辑一个相当复杂的查询非常很麻烦。并允许用户使用视觉设计器插入/删除数据是一种射击自己的方式。管理工作室的大小版本,基本SQL和受限服务器用户的知识将会做得更好。

如果你仍然倾向于设计这个应用程序,你将需要NHibernate。更确切地说,Criteria Queries将完成这项工作,因为它们非常接近你需要的地图。

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

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

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<Person>的类,并使用物理模型的唯一标识符填充其内部数据类型。这会使您的业务层与数据层可能发生的任何更改隔离开来,例如将int密钥标识符替换为Guid