Как реализовать DbContextOptionsBuilder в .NET Core - PullRequest
0 голосов
/ 14 марта 2019

Я новичок в ASP.Net Core и пытаюсь реализовать ASP.NET Core DI.

Я настроил, как показано ниже, в методе ConfigureServices в Startup.cs

services.AddScoped<DbContext, AutomationDbContext>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<IUserService, UserService>();

В UserService Constructor я пытаюсь использовать DI. Я думаю, что ниже НЕ правильный способ реализовать это.

public UserService(IHttpContextAccessor httpContextAccessor, AutomationDbContext automationDbContext, IConfiguration configuration)
    {
        this.configuration = configuration;
        this.optionsBuilder = new DbContextOptionsBuilder<AutomationDbContext>();
        var connectionString = this.configuration.GetConnectionString("Automation");
        this.optionsBuilder.UseSqlServer(connectionString);
        this.automationDbContext = new AutomationDbContext(this.optionsBuilder.Options);
        this.httpContext = httpContextAccessor.HttpContext;
    }

Мне не нравится строить optionsbuilder в конструкторе и получать строку подключения. Что было бы лучшим местом для сборки этих параметровBuilder и передачи в конструктор.

1 Ответ

1 голос
/ 14 марта 2019

Вам нужно использовать services.AddDbContext<TContext> вместо:

services.AddDbContext<AutomationDbContext>(o =>
    o.UseSqlServer(Configuration.GetConnectionString("Automation")));

Затем просто введите ваш контекст:

public UserService(IHttpContextAccessor httpContextAccessor, AutomationDbContext automationDbContext)

Что касается IHttpContextAccessor, вы должны просто использовать:

services.AddHttpContextAccessor();

Однако я бы настоятельно рекомендовал вам решительно подумать, действительно ли вам это нужно в вашем обслуживании или нет. Если вам нужно что-то вроде идентификатора текущего пользователя, оно должно быть передано в метод, который нуждается в нем, а не извлечено из вашего сервиса.

UPDATE

Так как он был задан, позвольте мне объяснить причины, по которым добавление вашего контекста в том виде, в котором вы сейчас находитесь, является неправильным, поскольку оно проливает немного света на работу DI в целом.

Во-первых, вы привязываете DbContext непосредственно к AutomationDbContext, что означает, что вы можете использовать только этот один контекст. Может быть, вам не нужно больше, чем один контекст ... сейчас. Это может измениться позже. Во-вторых, когда вы регистрируете сервис таким образом, вы можете вводить только абстрактный тип, то есть DbContext здесь. Регистрация службы буквально означает «когда вы видите DbContext, введите экземпляр AutomationDbContext». Если вы попытаетесь внедрить AutomationDbContext напрямую, как вы это делаете в своем контроллере, это фактически вызовет исключение, потому что этот тип на самом деле не зарегистрирован как сервис: DbContext is. В-третьих, AddScoped не предоставляет реальной возможности конфигурировать контекст, что, конечно, является частью, которую вы упустили. Есть способы обойти это, например использовать фабричную перегрузку AddScoped или определить OnConfiguring для вашего контекста, но оба они не соответствуют стандартному использованию правильного метода: AddDbContext<TContext>

Несмотря на это, есть и четвертая причина, по которой вы можете использовать AddDbContextPool<TContext> вместо AddDbContext<TContext> для пула соединений. Нет другого способа настроить это, поэтому, если вы действительно хотите / нуждаетесь в пуле соединений, вы никогда не добьетесь этого с AddScoped.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...