Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are expected results when optionsBuilder is defined in both DbContext.OnConfiguring and AspCore Startup.ConfigureServices?

My ASP.NET core has this class which gets called first

public class Startup
{ 
    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
         services.AddDbContext<IssuerContext>(options => 
             options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddMvc();
    }

And my context has this:

public class IssuerContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var connString = "Server=(localdb)\\mssqllocaldb;Database=HavenServer;ConnectRetryCount=0;Trusted_Connection=True;MultipleActiveResultSets=true\"";
        optionsBuilder
            .UseLoggerFactory(MyConsoleLoggerFactory)
            .EnableSensitiveDataLogging(false)
            .UseSqlServer(connString, options => options.MaxBatchSize(150));

        base.OnConfiguring(optionsBuilder);
    }

What is the expected SQLServer options configuration when seemingly overlapping options are defined in two locations?

like image 345
makerofthings7 Avatar asked Mar 29 '18 17:03

makerofthings7


2 Answers

It is explained in the Configuring a DbContext section of the documentation:

The DbContextOptions can be supplied to the DbContext by overriding the OnConfiguring method or externally via a constructor argument.

If both are used, OnConfiguring is applied last and can overwrite options supplied to the constructor argument.

In general, inside your OnConfiguring override you are supposed to check DbContextOptionsBuilder.IsConfigured property:

Gets a value indicating whether any options have been configured.

This can be useful when you have overridden OnConfiguring to configure the context, but in some cases you also externally provide options via the context constructor. This property can be used to determine if the options have already been set, and skip some or all of the logic in OnConfiguring.

E.g.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
        var connString = "Server=(localdb)\\mssqllocaldb;Database=HavenServer;ConnectRetryCount=0;Trusted_Connection=True;MultipleActiveResultSets=true\"";
        optionsBuilder
            .UseLoggerFactory(MyConsoleLoggerFactory)
            .EnableSensitiveDataLogging(false)
            .UseSqlServer(connString, options => options.MaxBatchSize(150));
    }
    base.OnConfiguring(optionsBuilder);
}
like image 77
Ivan Stoev Avatar answered Sep 27 '22 21:09

Ivan Stoev


Generally, both options will be applied with the configuration from the "OnConfiguring" method being "applied in addition to configuration" from the "ConfigureServices" method. ConfigureServices is used to setup dependency injection for your DbContext so it will use those options as a constructor parameter. Any additional configuration done in the OnConfiguring method will be appended or override configuration from the StartUp class. However, in the example you have provided, you do not have a constructor in your DbContext, so configuration from the Startup class will not be used.

Docs

like image 43
jcwmoore Avatar answered Sep 27 '22 21:09

jcwmoore