【问题标题】:How to change initial catalog at runtime when using a connection string and dapper使用连接字符串和 dapper 时如何在运行时更改初始目录
【发布时间】:2020-08-05 16:52:49
【问题描述】:

我正在编写一个 MVC C# 应用程序。我使用 dapper 作为轻量级 ORM。我的连接字符串是用服务器和初始目录定义的,目前如果我需要访问不同的数据库,我定义另一个连接字符串,并使用 Ninject 绑定来使用基于我正在注入的管理器的特定连接字符串,就像这样:

public class NinjectBindings : NinjectModule
{
    public override void Load()
    {
        Bind<IDbConnection>().To<SqlConnection>()
           .WhenInjectedInto<DashboardManager>()
           .InRequestScope()
           .Named("myDashboard")
           .WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["dbDashboard"].ConnectionString);

        Bind<IDbConnection>().To<SqlConnection>()
           .WhenInjectedInto<ScoreboardManager>()
           .InRequestScope()
           .Named("myScoreboard")
           .WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["dbScoreboard"].ConnectionString);

    }
}

不幸的是,如果我在同一个管理器中有代码需要调用与最初指定的目录不同的数据库中的存储过程,这将不起作用。

问题是:我可以只定义一个连接字符串,丢失上面所有的 ninject 绑定内容,然后简单地将初始目录更改为指向不同数据库的点吗?

【问题讨论】:

    标签: c# asp.net-mvc-4 connection-string dapper ninject.web.mvc


    【解决方案1】:

    您的绑定是否需要NamedWhenInjectedInto 约束?

    我相信你有一个类同时需要connectionstrings,这可以使用Named绑定来实现:

    Bind<IDbConnection>().To<SqlConnection>()
       .InRequestScope()
       .Named("myDashboard")
       .WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["dbDashboard"].ConnectionString);
    
    Bind<IDbConnection>().To<SqlConnection>()
       .InRequestScope()
       .Named("myScoreboard")
       .WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["dbScoreboard"].ConnectionString);
    

    您的班级可以同时获得这两个连接:

    public class ClassWith2DbDependency // <-- I would question this class for SRP violation
    {
        private readonly IDbConnection _dashboardConnection;
        private readonly IDbConnection _scoreboardConnection;
    
        public ClassWith2DBDependency(
            [Named("myDashboard")] IDbConnection dashboardConnection
            [Named("myScoreboard")] IDbConnection scoreboardConnection)
        {
            _dashboardConnection = dashboardConnection;
            _scoreboardConnection = scoreboardConnection;
        }
    
        public void WriteTo2Dbs()
        {
            // execute dashboard DB procedure
            // execute scoreboard DB procedure
        }
    }
    

    我可以只定义一个连接字符串,失去所有的ninject绑定 上面的东西,只需将初始目录更改为指向 动态不同的数据库?

    更改 Initial Catalog 不会影响现有的 SqlConnection。可以自己管理依赖,但还是需要2个connectionstrings:

    public class ClassWith2DbDependency
    {
        public void WriteTo2Dbs()
        {
            var dashboardCon = ConfigurationManager.ConnectionStrings["dbDashboard"].ConnectionString;
            using (SqlConnection connection = new SqlConnection(dashboardCon))
            {
                // execute dashboard DB procedure
            }
    
            var scoreboardCon = ConfigurationManager.ConnectionStrings["dbScoreboard"].ConnectionString;
            using (SqlConnection connection = new SqlConnection(scoreboardCon))
            {
                // execute scoreboard DB procedure
            }
        }
    }
    
    

    但是,我确实推荐这种方法,上面的类违反了 DI 原则,Opaque Dependencies


    我没有看到你的代码,但听起来你使用的不是Repository Pattern?这可能是一个不错的选择...

    【讨论】:

    • 谢谢,我使用了你的第一个解决方案。关于如何使命名字符串通用的任何想法,以便我可以在它被 DI 输入到管理器之前以某种方式传递它? [Named("thisStringMightChangeOnTheFly")] IDbConnection 仪表板连接
    • 您可以实现类似this 的东西,但请记住,更改connectionString 不会影响现有连接。
    猜你喜欢
    • 2019-04-02
    • 1970-01-01
    • 2017-11-17
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多