【问题标题】:How to access DB connectionstring in DAL from presentation layer如何从表示层访问 DAL 中的数据库连接字符串
【发布时间】:2018-04-23 12:51:08
【问题描述】:

我有具有多个层的 .net core 2.0 Web API 项目,即 Presentation、BLL、DAL... 我的连接字符串位于表示层中的 appsettings.json 文件中。我的 DAL 负责根据该连接字符串从数据库中获取数据。如何读取该 json 文件或将连接字符串传递给 DAL。
附:表示层依赖于 BLL,BLL 依赖于 DAL。

appsettings.json

{
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  },
  "ConnectionStrings": {
    "MsSqlConnectionString": "Data Source=myServerName;Database=myDB;User Id=myUserID;Password=myPWd;"
  }
}


DAL 类

protected readonly string _connectionString;
protected IDbConnection _connection { get { return new SqlConnection(_connectionString); } }

public BaseDal()
{
    _connectionString = "<<How to get connectionstring from appsetting.json>>";
}


ChildDAL

public class MyDAL : BaseDal, IMyDAL
{
    ILogger _log;
    public MyDAL(ILoggerFactory loggerFactory)
    {
        _log = loggerFactory.CreateLogger("ChildDAL");
    }
    public async Task<IEnumerable<MyModel>> MyMethod(Dto criteria)
    {
        StringBuilder sql = new StringBuilder();

        sql.Append("SELECT * FROM table");
        string query = sql.ToString();
        // custom mapping
        DapperCustomMapping<MyModel>();

        using (IDbConnection dbConnection = _connection)
        {
            return await dbConnection.QueryAsync<MyModel>(query);
        }
    }
}

Startup.cs

public class Startup
{
    public IConfigurationRoot Configuration { get; }

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
             .SetBasePath(env.ContentRootPath)
             .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);

        Configuration = builder.Build();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        //loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
        loggerFactory.AddLog4Net();

        app.UseErrorWrappingMiddleware();
        app.UseStatusCodePagesWithReExecute("/error/{0}");
        app.UseExceptionHandler("/error/500");

        // CORS: UseCors with CorsPolicyBuilder.
        app.UseCors("AllowSpecificOrigin");

        // MVC
        app.UseMvc();

        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        //Enable middleware to serve swagger - ui
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("../swagger/v1/swagger.json", "My API v1");
        });
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // Read appsettings.json to get allowed origins
        var whiteList = new List<string>();
        var myArraySection = Configuration["AllowedOrigin"];
        if (!String.IsNullOrEmpty(myArraySection))
        {
            foreach (var d in myArraySection.Split(','))
            {
                whiteList.Add(d.Trim());
            }
        }

        // CORS
        services.AddCors(options =>
        {
            options.AddPolicy("AllowSpecificOrigin",
                policy => policy.WithOrigins(whiteList.ToArray()));
        });

        // Add framework services.
        services.AddMvc(options =>
        {
            // install global fitler on all controllers and actions.
            options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSpecificOrigin"));
            options.Filters.Add(new ValidateModelAttribute());
        })
        // tell how to find the fluent validations
        .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<ContactQueryDtoValidator>());

        // Register the Swagger generator
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = "API", Version = "v1" });
        });

        return ConfigureIoC(services);
    }

    public IServiceProvider ConfigureIoC(IServiceCollection services)
    {
        var container = new Container();
        container.Configure(config =>
        {
            config.Scan(_ =>
            {
                _.AssemblyContainingType(typeof(Startup)); // web api
                _.AssemblyContainingType(typeof(HelloBLL)); // Unused BLL
                _.AssemblyContainingType(typeof(HelloDAL)); // Unused DAL
                _.TheCallingAssembly();
                _.WithDefaultConventions();

            });

            config.Populate(services);
        });
        return container.GetInstance<IServiceProvider>();
    }
}

【问题讨论】:

  • 传递给 DAL 的连接字符串在哪里?
  • 您如何创建BaseDal 的实例?
  • @KirkLarkin 正确的问题来了。我正在继承 BaseDAL。查看我更新的问题
  • 您在 DI 注册MyDAL 吗?如果是这样,您能否包含代码以便我提供示例解决方案?

标签: c# connection-string asp.net-core-2.0 asp.net-core-webapi


【解决方案1】:

另一种访问配置文件的方法,引用自https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-2.1&tabs=basicconfiguration

确保您导入下面的库

using Microsoft.Extensions.Configuration;
using System.IO;

    public BaseDal()
    {
        var builder = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json");

        Configuration = builder.Build();
        var _connectionString = Configuration.GetConnectionString("CONNECTION_STRING")
    }

【讨论】:

  • 错误:当前上下文中不存在名称“配置”。然后在导入 System.Configuration 后出现错误:命名空间“System.Configuration”中不存在类型或命名空间名称“GetConnectionString”(您是否缺少程序集引用?)
  • 我的错误,如果你查看你的 startup.cs 类,你会发现一个配置字段,你可以使用它来引用你的 appsettings.json 文件。
  • 它使用 Microsoft.Extensions.Configuration。使用后,我将 Configuration 设为 null,然后 object ref not set 错误。 public IConfigurationRoot Configuration; protected readonly string _connectionString; _connectionString = Configuration.GetConnectionString("MsSqlConnectionString");
  • 下一个选项不会出错,我不知道引用连接字符串的干净方法。
  • NP!感谢您对此进行调查。
【解决方案2】:

假设您已经在表示层的startup.cs文件中注册了该部分。

  public class AppSettings
    {
        public string MsSqlConnectionString{ get; set; }
    }

   //registering in ConfigureServices method of Startup.cs
   services.Configure<AppSettings>(Configuration.GetSection("ConnectionStrings"));

要在 DAL 层中访问,您还必须在那里创建 AppSettings 类,然后只需使用

public BaseDal(IOptions<AppSettings> app)
{
    _connectionString = app.Value.MsSqlConnectionString;;
}

编辑

收到时

错误:没有给出与所需参数相对应的参数 'BaseDal.BaseDal(IOptions)'的形参'app'

这意味着你没有给它必需的参数。可以调用基类并通过调用:base(parameters...)构造函数给required参数。

public class MyDAL : BaseDal, IMyDAL
{
    ILogger _log;
    public MyDAL(ILoggerFactory loggerFactory,IOptions<AppSettings> app):base(app)
    {
        _log = loggerFactory.CreateLogger("ChildDAL");
    }
}

【讨论】:

  • 我应该早点提到这一点。我有多个从 BaseDAL 继承的子类,所以如果我添加参数化构造函数,我会从子类中得到一堆错误来传递该参数。错误:没有给出与“BaseDal.BaseDal(IOptions)”的所需形式参数“app”相对应的参数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多