zoukankan      html  css  js  c++  java
  • 数据库连接字符串

     

    WebApi 插件式构建方案:集成加载数据库连接字符串

    对服务来说,一般都会用到数据库。而今,在微软的大环境下,使用 EF 的人肯定会越来越多。但是,使用 EF 有个问题,一个是使用缺省的构造函数,缺省从 ConfigurationManager.ConnectionStrings 中获取数据库连接;另外一种就是在构造的时候,手工指定数据库连接字符串。

    对开发者来说,最好的办法就是不去管它,直接用缺省的构造函数就好。但是插件式的开发,系统怎么知道你数据库的连接字符串放在哪呀?主要的问题就在于其数据库连接字符串,并没有添加到 Web.Config 文件中,所以使用缺省构造函数,会出现无法找到配置的错误。

    有个最简单的解决办法:可以选择把数据库连接字符串放到 Web.config 中,这样就能解决所有问题。可这样做,插件的配置侵入到主站了!但是,话说回来,我相信大部分用 WebApi 框架的人,都是这样干的。这样用,日后模块自己的数据库连接字符串增删改升级的时候,还得更改主站的配置。

    这是绕不过去的一个坎!把本来一个的配置分散到两个地方,每次变动就必须修改这两处地方。日后维护的时候,这就是个坑!在知道的人离职后,后续的人根本就找不到问题原因。

    插件管理自己的数据库连接字符串

    理想的情况下,我们可以在第一次系统初始化的时候,给 ConfigurationManager.ConnectionStrings 这个集合中添加我们的数据库配置,这样就能在解析的时候找到配置了。顺着这个思路继续想,微软的反射很强大,可以更改本来不可以更新的数据。所以,就有了下面这段代码:

    public void Configurate(System.Configuration.Configuration[] configurations)
    {
        var meta = ((TypeX)ConfigurationManager.ConnectionStrings.GetType()).GetField("bReadOnly");
        meta.SetValue(ConfigurationManager.ConnectionStrings, false);
    
        configurations.SelectMany(p => p.ConnectionStrings.ConnectionStrings.OfType<ConnectionStringSettings>())
                      .Where(p => ConfigurationManager.ConnectionStrings.IndexOf(p) < 0)
                      .ForEach(ConfigurationManager.ConnectionStrings.Add);
    
        meta.SetValue(ConfigurationManager.ConnectionStrings, true);
    }

    这段代码的意思是,把各个模块的数据库连接字符串文件加载到列表中,然后通过反射开启赋值,加到 ConfigurationManager.ConnectionStrings 集合中。

    要完成这个功能,我们尚需做的就是找到每个模块的数据库连接字符串文件,然后加载获得上面这个函数的参数。考虑到我们为每个模块定义了一个配置文件,所以这里为其添加一个配置就好了:

    <?xml version="1.0" encoding="UTF-8"?>
      <configuration enabled="true">
        <description>授权支持插件</description>
        <assemblies>
          <add type="relative">bin/Intime.AuthorizationService.dll</add>
          <add type="relative">bin/Intime.AuthorizationService.Services.dll</add>
          <add type="relative">bin/Intime.AuthorizationService.Data.dll</add>
          <add type="relative">bin/Intime.AuthorizationService.Data.Repository.dll</add>
        </assembiles>
        <appConfig type="relative">bin/Intime.AuthorizationService.Data.Repository.dll.config</appConfig>
    </configuration>

    参考 appConfig 配置节,我们可以得到模块的配置文件绝对路径,再和 DynamicModules 配合,用下面这段代码就可以得到 System.Configuration.Configuration[] configurations 这个参数了:

    public void Configurate(HttpConfiguration configuration)
    {
        var items = ServiceLocator.Current.GetAllInstances<IAppConfigHandler>().ToArray();
        if (items.Any())
        {
            var data = DynamicModules.Instance
                .Modules
                .Where(p => !string.IsNullOrWhiteSpace(p.Configuration.AppConfig))
                .Select(p =>
                {
                    var fullFilePath = Path.Combine(p.Path, p.Configuration.AppConfig);
    
                    return ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap { ExeConfigFilename = fullFilePath }, ConfigurationUserLevel.None);
                })
                .ToArray();
    
            items.ForEach(p => p.Configurate(data));
        }
    }

    可以看到,在这里我用了 IAppConfigHandler 接口,这样就可以扩展其他的配置了,不仅限于 ConnectionStrings 。

    另外,上面这段代码缺点东西,自行脑补吧,很容易就看明白的。

     
     
  • 相关阅读:
    Assetbundle资源单一打包,以及加载方法
    VS2010 Chromium编译
    一道思考题
    Windbg源码调试
    C++ static_cast dynamic_cast reinterpret_cast const_cast转换
    条件断点设置
    FFmpeg 2.0编译配置
    error LNK2001: 无法解析的外部符号 _IID_IDirectDraw7
    Windbg常用命令
    DDraw绘图
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4173291.html
Copyright © 2011-2022 走看看