it-roy-ru.com

Передача строки подключения приложения в библиотеку классов репозитория в ASP.NET 5 с использованием IConfigurationRoot

У меня есть веб-приложение ASP.NET 5 MVC и в Startup.cs я вижу, что публичное свойство 

IConfigurationRoot Configuration 

устанавливается на builder.Build();

Через веб-приложение MVC я могу просто сделать

Startup.Configuration["Data:DefaultConnection:ConnectionString"]

чтобы получить строку conn из файла appsettings.json.

Как я могу получить строку подключения, указанную в ASP.NET 5 MVC appsettings.json, передаваемую в мою библиотеку классов репозитория с использованием конструктора?

Обновление:
Вот базовый репозиторий, от которого наследуются все остальные репозитории (как вы можете видеть, у меня есть жестко закодированная строка подключения здесь):

public class BaseRepo
{
    public static string ConnectionString = "Server=MYSERVER;Database=MYDATABASE;Trusted_Connection=True;";

    public static SqlConnection GetOpenConnection()
    {
        var cs = ConnectionString;
        var connection = new SqlConnection(cs);
        connection.Open();
        return connection;
    }
}

В моем веб-приложении asp.net 5 в моем файле appsettings.json есть следующее, что эквивалентно добавлению строки подключения к web.config в веб-приложении .net 4.5:

  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=MYSERVER;Database=MYDATABASE;Trusted_Connection=True;"
    }
  }

Кроме того, в моем веб-приложении asp.net 5 в файле Startup.cs есть следующий код по умолчанию, который загружает конфигурацию сайтов в открытое свойство типа IConfigurationRoot:

 public IConfigurationRoot Configuration { get; set; }
// Class Constructor
        public Startup(IHostingEnvironment env)
        {
            // Set up configuration sources.
            var builder = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json")
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

            if (env.IsDevelopment())
            {
                // For more details on using the user secret store see http://go.Microsoft.com/fwlink/?LinkID=532709
                builder.AddUserSecrets();
            }

            builder.AddEnvironmentVariables();
            Configuration = builder.Build();
        }

Теперь в моем веб-приложении asp.net, если я хочу получить доступ к любой из настроек приложения, я могу просто сделать следующее: Startup.Configuration["Data:DefaultConnection:ConnectionString"]

Но, к сожалению, я не могу сделать это из моей библиотеки классов ..

Если кто-то хочет попробовать это выяснить, вот шаги для воспроизведения:

  1. Создайте новое ASP.NET 5 MVC Web App. 
  2. Добавьте в проект другой проект типа Class Library (Package). 
  3. Узнайте, как передать наборы приложений из приложения ASP.NET 5 MVC в библиотеку классов

После обновления я все еще не могу получить его. Вот мой код:

public class BaseRepo
{
    private readonly IConfigurationRoot config;

    public BaseRepo(IConfigurationRoot config)
    {
        this.config = config;
    }
}

Это объявление класса не работает, так как BaseRepo теперь требует конструктор param.

public class CustomerRepo : BaseRepository, ICustomerRepo
{
    public Customer Find(int id)
    {
        using (var connection = GetOpenConnection())
        {
            ...
        }
    }
}
21
Blake Rivell

в вашем файле Startup.cs добавьте следующий метод

public void ConfigureServices(IServiceCollection services) {
    services.AddSingleton(_ => Configuration);
}

затем обновите свой класс BaseRepo следующим образом

public class BaseRepo {
    private readonly IConfiguration config;

    public BaseRepo(IConfiguration config) {
        this.config = config;
    }

    public SqlConnection GetOpenConnection() {
        string cs = config["Data:DefaultConnection:ConnectionString"];
        SqlConnection connection = new SqlConnection(cs);
        connection.Open();
        return connection;
    }
}
27
Manos Pasgiannis

ASP.NET предоставляет свой собственный способ передачи параметров конфигурации.

Предположим, у вас есть это в вашем appSettings.json:

{
  "Config": {
    "Setting1": 1,
    "Setting2": "SO"
  }
}

Тогда вам нужен такой класс:

public class MyConfiguration
{
    public int Setting1 { get; set; }

    public string Setting2 { get; set; }
}

Это позволяет вам настроить службу с этой конфигурацией, добавив следующую строку

services.Configure<MyConfigurationDto>(Configuration.GetSection("Config"));

ConfigureServices.

Затем вы можете внедрить конфигурацию в конструкторы, выполнив следующие действия:

public class SomeController : Controller
{
    private readonly IOptions<MyConfiguration> config;

    public ServiceLocatorController(IOptions<MyConfiguration> config)
    {
        this.config = config;
    }

    [HttpGet]
    public IActionResult Get()
    {
        return new HttpOkObjectResult(config.Value);
    }
}

Этот пример для контроллеров. Но вы можете сделать то же самое с другими слоями вашего приложения.

10
Chrono

У меня есть конструктор в моем классе репозитория, который принимает строку подключения БД в качестве параметра. Это работает для меня, когда я добавляю свой репозиторий для инъекций. В ConfigureServies () файла startup.cs добавьте это:

services.AddScoped<IRepos>(c => new Repos(Configuration["DbConnections:ConnStr1"]));

IRepos.cs - это интерфейс, Repos.cs - это класс, который его реализует. И, конечно же, Configuration - это просто ссылка на встроенный объект IConfigurationRoot.

2
Matthew Allen

Уже есть метод расширения, который вы можете использовать для получения строк подключения, в частности, из aspsettings.json.

  1. Определите строки подключения в appsettings.json следующим образом:

     {
         "ConnectionStrings": {
             "Local": "Data source=.\\SQLExpress;Initial Catalog=.......",
             "Test:": "Data source=your-server;......"
         },
         "Logging": {
             "IncludeScopes": false,
             "LogLevel": {
                 "Default": "Debug",
                 "System": "Information",
                 "Microsoft": "Information"
             }
         }
    }
    
  2. В вашем методе public void ConfigureServices(IServiceCollection services) внутри вашего Startup.cs вы можете получить строку подключения следующим образом:

    var connectionString = this.Configuration.GetConnectionString("Local");
    
  3. Расширение GetConnectionString взято из Microsoft.Extensions.Configuration.
  4. Наслаждаться :)

ОБНОВЛЕНИЕ

Сначала я не хотел вдаваться в подробности, потому что этот вопрос уже помечен как ответ. Но я думаю, что я могу показать свои 2 цента здесь.

Если вам нужен весь объект IConfigurationRoot, введенный в контроллеры, @Chrono показал правильный путь.

Если вам не нужен весь объект, вы должны просто получить строку подключения, передать ее в DbContext внутри вызова ConfigureServices() и вставить DbContext в контроллеры. @Prashant Lakhlani показал это правильно.

Я просто говорю, что в посте @Prashant Lakhlani вы можете использовать расширение GetConnectionString вместо того, чтобы немного очистить код.

1
David Liang

Если ConfigureServices в вашем проекте startUp.cs содержит

services.AddEntityFramework()
             .AddSqlServer()
             .AddDbContext<YourDbContext>(options =>
                 options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

и ваш репозиторий CS файл имеет инъекцию конструктора, как показано ниже

public class MyRepo : IRepo
{
    private readonly YourDbContext dbContext;
    public MyRepo(YourDbContext ctx)
    {
        dbContext = ctx;
    }
}

YourDbContext будет автоматически разрешен.

1
Prashant Lakhlani

Немного другой подход заключается в создании статического класса в вашей библиотеке классов, для которого вы вызываете метод из метода Configure(..)- в Startup.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ...
    ConnectionManager.SetConfig(Configuration);
}

В этом случае я добавил конфигурацию как синглтон в ConfigureServices:

services.AddSingleton(_ => Configuration);

Мой ConnectionManager выглядит так:

public class ConnectionManager
{
    private static IConfiguration currentConfig;

    public static void SetConfig(IConfiguration configuration)
    {
        currentConfig = configuration;
    }

    /// <summary>
    /// Get a connection to the database.
    /// </summary>
    public static SqlConnection GetConnection
    {
        get
        {
            string connectionString = currentConfig.GetConnectionString("MyConnection");
            // Create a new connection for each query.
            SqlConnection connection = new SqlConnection(connectionString);
            return connection;
        }
    }
}

Это может иметь или не иметь некоторые проблемы, касающиеся времени жизни объектов и тому подобное, и я, конечно, не фанат классов static, но, насколько я могу судить, это жизнеспособный подход. Вместо передачи Configuration вы можете даже извлечь ConnectionString из конфигурационного файла и отправить только это.

1
Ruben Steins

Вам нужно создать класс в проекте библиотеки классов, чтобы получить доступ к appsettings.json в проекте веб-сайта и вернуть строку подключения.

{
    private static string _connectionString;

    public static string GetConnectionString()
    {
        if (string.IsNullOrEmpty(_connectionString))
        {
            var builder = new ConfigurationBuilder()
           .AddJsonFile("appsettings.json");
            Configuration = builder.Build();
            _connectionString = Configuration.Get<string>("Data:MyDb:ConnectionString");
        }
        return _connectionString;
    }
    public static IConfigurationRoot Configuration { get; set; }

}
0
samvietnam