2

我们正在制作一个 ASP.Net 应用程序。我们希望我们的应用程序至少与 DB 无关,最值得注意的是与 SQL Server 和 PostgreSQL 兼容。这样做的最佳方法是什么?有哪些常见的陷阱?还有一个类或其他东西已经抽象出诸如SqlConnectionPostgreSQL 用于连接的东西之间的区别吗?

(我们希望与数据库无关,因此我们可以在此处(在开发中以及稍后在我们自己的托管中)使用 PostgreSQL,如果他们愿意,让我们的自托管客户使用 Sql Server)

4

8 回答 8

5

所有 ADO.Net 提供程序都扩展了基本接口:

因此,理论上您可以针对抽象接口编写整个 DAL(数据访问层)并利用任何提供者,包括 MySQL 等第三方提供者。在实践中,没有一个凡人能够成功地完成这个把戏。一方面,这些接口很难编程,而且任何超出演示软件的应用程序都会很快遇到 SQL 方言不兼容的问题。

更可行的方法是满足多个目标目的地并开发特定的 DAL。实体框架和存储库模式以及 nHibernate 和所有这些帮助,但都没有解决根本问题。

于 2009-12-18T17:37:31.200 回答
1

您可以使用实体框架。这样你就可以使用一个单一的编程模型。

http://msdn.microsoft.com/en-us/library/aa697427(VS.80).aspx

http://www.devart.com/dotconnect/postgresql/

于 2009-12-18T17:06:31.903 回答
1

如果您只想直接使用 ADO.NET,您可以使用 DbProviderFactory 来抽象出您正在使用的提供程序(SqlClient、OleDb 等)。通常你将它与 <connectionStrings> 配置元素结合使用,代码如下:

ConnectionStringSettings c = ConfigurationManager.ConnectionStrings[name];
DbProviderFactory factory = DbProviderFactories.GetFactory(c.ProviderName)
...
IDbConnection connection = _factory.CreateConnection();
connection.ConnectionString = c.ConnectionString;
...

MSDN上有很多信息。

当然,这并不能帮助您解决不同提供者之间的 SQL 语法差异——您需要一种最低公分母方法来处理多个提供者。这会影响诸如参数语法之类的东西(例如,SQL Server 的 @ 前缀,仅用于 OleDb 的位置参数,...)。

于 2009-12-18T17:38:21.263 回答
0

我只是为我的数据源创建一个接口,然后为我需要使用的每种数据源类型实现它。通常它们看起来像这样:

public interface IMyProjectDataSource
{
    IEnumerable<string> GetUserNames();
    void AddUser(string userName);
}

public class SqlServerMyProjectDataSource : IMyProjectDataSource
{
    public SqlServerMyProjectDataSource(string connectionString)
    {
        //...
    }

    public IEnumerable<string> GetUserNames()
    {
        //...
    }

    public void AddUser(string userName)
    {
        //...
    }
}

public class PostgreSqlMyProjectDataSource : IMyProjectDataSource
{

    public IEnumerable<string> GetUserNames()
    {
        //...
    }

    public void AddUser(string userName)
    {
        //...
    }
}

public class HttpCacheSqlMyProjectDataSource : IMyProjectDataSource
{
    public HttpCacheSqlMyProjectDataSource(IMyProjectDataSource parentMyProjectDataSource)
    {

    }

    public IEnumerable<string> GetUserNames()
    {
        //...
    }

    public void AddUser(string userName)
    {
        //...
    }
}

我也喜欢这个,因为它允许您将它们“链接”在一起。例如,您可以像这样进行所有数据源缓存:

public class HttpCacheSqlMyProjectDataSource : IMyProjectDataSource
{
    public HttpCacheSqlMyProjectDataSource(IMyProjectDataSource parentMyProjectDataSource)
    {
            //...
    }

    public IEnumerable<string> GetUserNames()
    {
        //...
    }

    public void AddUser(string userName)
    {
        //...
    }
}

最困难的部分是决定如何创建它,特别是如果您打算将多个链接在一起。为此,我通常将它作为单例存储在 Global.asax.cs 中,并从 .config 文件中的类型名称创建它。您可以使用 Type.GetType() 然后 Activator.CreateInstance() 来执行此操作,并且无论 .config 中的数据源是什么,我所拥有的大部分链接都将完成,因此我不必担心创建一些某种“构造函数”类型或复杂的.config。

希望这是有道理的。这可能不是所有情况下最好的,但我很幸运。

于 2009-12-18T17:19:39.427 回答
0

实体框架是 Shiraz 提到的一个选项。您还可以考虑其他 ORM 解决方案,例如NHibernate

于 2009-12-18T17:20:10.410 回答
0

与数据库无关的应用程序的最佳解决方案通常是ORMthis 标签)。.NET有很多-这个问题将为您提供一些关于选择哪一个的指导。

最受欢迎的三个是:

于 2009-12-18T17:25:55.937 回答
0

我建议使用某种存储库模式。

这不是灵丹妙药,可以让您免于针对每种 DBMS 风格进行黑客攻击,但如果您希望它从一开始就可维护,这是 ORM 不提供的东西,那么这就是要走的路。

http://blog.wekeroad.com/2008/04/07/asp-net-mvc-mvc-storefront-part-2

于 2009-12-18T17:30:04.073 回答
0

在非常高的层次上,您可能希望使用比 SqlConnection、SqlCommand 和 Sql* 类更抽象您的数据库的东西。因此,当人们说要使用 ORM 时,他们是非常正确的。ORM 为您提供了该级别的抽象。

但是为了抽象出 SqlCommand 和 SqlConnection,System.Data 命名空间中有接口。IDbConnection、IDbCommand 等已经在框架中,您可以针对它们进行编码。接下来的问题是找到一种创建具体类的方法,您可以使用 IoC 容器或提供者模式来解决这个问题。

于 2009-12-18T17:34:29.337 回答