【问题标题】:Handling multiple connection strings in ONE DataAccess Layer在 ONE 数据访问层中处理多个连接字符串
【发布时间】:2010-08-03 07:49:15
【问题描述】:

我有一个有趣的困境。我目前有一个必须与多个域一起使用的 DataAccess 层,并且每个域都有多个数据库存储库,具体取决于调用的存储过程。到目前为止,我只是使用 SWITCH 语句来确定应用程序正在运行的机器,并从 Web.config 返回适当的连接字符串。现在我有一项艰巨的任务,即在同一个 SQL 服务器中处理多个数据库存储库,并且我喜欢根据调用的存储过程动态确定连接字符串。也许我想太多了,但我无法思考我将如何处理这个问题。

【问题讨论】:

  • 您的 DAL 结构如何?只有一个大会吗?

标签: c# .net sql


【解决方案1】:

我要说的第一件事是您的设计中可能存在缺陷,因为跨多个数据库调用多个存储过程的需要并不常见。

但是,有许多选项可用,例如:

  1. 在 web.config 中存储存储过程列表以及每个存储过程的相应连接字符串,并在运行时检索它们。
  2. 有一个列出存储过程和连接字符串的集中表(因此您在 web.config 中只有一个连接字符串,只有一个指向存储过程连接字符串的中心表)。

【讨论】:

  • 我不同意存在缺陷,但同意它不常见。数据访问层旨在覆盖复杂的数据源 - 关键是您不知道数据来自哪里,访问层知道。我们的系统具有多个数据库和基于文件的保存,所有这些都被 DAL 隐藏。
  • 我同意亚当的观点,这不是缺陷,而是不常见。我在一个应用程序中工作,其中分销商需要自己的数据库,但所有内容都从单个应用程序运行,基于登录的用户,存储库将通过构造函数进行实例化,并为分销商数据库获取连接字符串。虽然其他存储库是在没有连接字符串的情况下实例化的,但使用默认值来查询共享数据库。这对我们来说非常有效。
【解决方案2】:

如果您必须继续确定数据库是一个存储过程调用,那么在配置文件中,定义您自己的配置部分,将存储过程名称映射到连接字符串。这将是最明确的,但需要维护。

您也可以将其集中到一个较小的目录数据库中,该数据库根据存储过程名称存储连接字符串 - 然后您可以创建一个 SQL 脚本,通过查询其他数据库对象。

然后我会将它读入内存(缓存它),这样您就可以避免在应用程序的生命周期内多次调用此目录数据库。继续我可以推测出关于您的数据库整体结构的少量信息(并忽略这种结构是如何形成的问题),我会说这是一个可管理的解决方案。

您可以通过使用负责返回适合给定过程名称的连接的基本 DAL 类来改进此解决方案 - 因此任何代码更改只需在一个地方发生即可返回不同的连接。其余代码调用GetConnection("getCustomers") 并愉快地忽略了细节。

【讨论】:

    【解决方案3】:

    如果您可以真正根据存储过程名称的唯一性映射单个连接字符串,一个有趣的尝试是在应用程序启动时从连接字符串列表中动态发现可用的存储过程并缓存映射。

    您似乎可以使用普通的 ConnectionStrings 配置来命名(分类)您的连接字符串。在您的代码中的某个时刻,您专门调用了一个存储过程。该调用是否还可以指定要使用的连接字符串的键?即:报告、成员等。

    <connectionStrings>
        <add name="Reporting" connectionString="<your connection string>" ... />
        <add name="Member" connectionString="<another connection string>" ... />
    </connectionStrings>
    

    对 DAL 的调用可能如下所示:

    var result = ExecStoredProcedure("Reporting", "up_SomeProcedure");
    

    【讨论】:

      【解决方案4】:

      假设您的 DAL 只是一个试图为多个不同数据库操作数据的程序集。我建议将代码拆分为每个数据库的单独程序集。然后你可以有每个程序集的具体配置信息,代码只会看执行程序集的具体配置信息。

      例如,假设您有一个 Movies 数据库和一个 Books 数据库。您将创建一个库,该库知道如何操作电影数据库中的数据,并且创建、编辑和查询电影所需的所有代码和存储过程都将在该库中。这个库会有它自己的配置信息,包括到数据库的连接字符串。

      与您的图书数据库交互类似,您将拥有一个单独的库,其中包含用于创建、编辑和查询图书信息的所有存储过程。同样,这将有它自己的配置信息,包括连接字符串。

      这种方法可以灵活地添加更多数据源,并相互独立地配置它们。

      如果您愿意,当然可以拥有另一个库来处理可能需要访问两个数据库的事务,并引用前面提到的库中的代码。

      【讨论】:

        【解决方案5】:

        这确实是一个有趣的挑战。从设计的角度来看,这可以通过多种方式解决,但它们似乎都有点损坏。

        在这种情况下,唯一真正对我有用的是:

        在每台服务器上创建一个过程数据库,并在该数据库上拥有调用真实过程的“接口”过程。

        喜欢:

        CREATE PROC pr_GetAddress
        (
            @addressId int
        )
        AS
        BEGIN
            exec pubs.dbo.pr_GetAddress @addressId
        END
        

        这样您就可以保留现有代码。

        您可以使用代码生成来为“接口”过程创建 sql 语句。

        添加:

        这让我突然想到...为什么不使用 Linq-to-Sql DataContext 来做你的事情?

        我只是在这里玩了这个 sn-p:

        public class ExperimentalDataContext: DataContext
        {
            public ExperimentalDataContext(string connectionString) : base(connectionString) { }
        
            public IExecuteResult ExecuteMethod(object instance, MethodInfo methodInfo, params object[] parameters)
            {
                return this.ExecuteMethodCall(instance, methodInfo, parameters);
            }
        
            [Function(Name = "dbo.fx_Levenstein", IsComposable = true)]
            public static System.Nullable<double> fx_Levenstein([Parameter(DbType = "NVarChar(255)")] string firstword, [Parameter(DbType = "NVarChar(255)")] string secondword)
            {
                using (ExperimentalDataContext context = new ExperimentalDataContext(GetConnectionString("your-connectionstring")))
                {
                    return ((System.Nullable<double>)(context.ExecuteMethod(context, ((MethodInfo)(MethodInfo.GetCurrentMethod())), firstword, secondword).ReturnValue));
                }
            }
        
            private static string GetConnectionString(string key)
            {
                return ConfigurationManager.ConnectionStrings[key].ConnectionString;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-27
          • 2012-06-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多