Search code examples
c#entity-framework-core.net-6.0.net-8.0scaffold

Upgrade from .NET 6 to .NET 8: Custom Context with Configuration - DB First


I want to upgrade from .NET 6 to .NET 8. I have to use DB first approach. In .NET 6 I created a custom context to be able to pass a connectionString from the injected Configuration.

public partial class ScaffoldedCustomContext : ScaffoldedContext
{
    private IConfiguration _config;

    public ScaffoldedCustomContext(IConfiguration Configuration)
    {
        _config = Configuration;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(_config.GetValue<string>("connectionString"));
        }
    }
}

After "switching" to .NET 8 (package upgrades and changing my VS code launch.json) the DB scaffold creates the following context file:

public partial class ScaffoldedContext : DbContext
{
    public ScaffoldedContext(DbContextOptions<ScaffoldedContext> options)
        : base(options)
    {
    }
    ...
}

with .net6 I was also given an empty default constructor:

public ScaffoldedContext()
{
}

In some of my methods for example in "Main" I needed to create a context like this:

 var _context = new ScaffoldedCustomContext(Configuration);

But with .NET 8 I get the error message that the required parameter options is missing.

How can I deal with that? Do I need to modify ScaffoldedCustomContext or do I have to create an options object - if yes, how?

Thank you.


Solution

    1. Arguably you don't need ScaffoldedCustomContext class at all. ScaffoldedContext is generated as partial so you should be able to just create a file named something like ScaffoldedContext.Custom and place it near the generated one (be sure to place them in the same namespace) and move all custom stuff there:

       public partial class ScaffoldedContext
       {
           private IConfiguration _config;
      
           public ScaffoldedContext(IConfiguration Configuration)
           {
               _config = Configuration;
           }
      
           protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
           {
               if (!optionsBuilder.IsConfigured)
               {
                   optionsBuilder.UseSqlServer(_config.GetValue<string>("connectionString"));
               }
           }
       }
      
    2. Without seeing your Main it is hard to tell what is the best course of action is but

      • Depending on the setup you potentially can just resolve the ScaffoldedContext in the Main - see for example Cannot resolve scoped service from root provider in ASP.NET Core 6
      • Similar to the previous - register context factory, resolve and use it to construct the context
      • Construct the options so you don't need the custom constructor:
        var options = new DbContextOptionsBuilder<ScaffoldedContext>()
            .UseSqlServer(Configuration.GetValue<string>("connectionString"))
            .Options;
        var ctx = new ScaffoldedContext(options);