Why cannot I set DbContextOptions with = operator?

1

Why cannot I use the following

IServiceCollection service= new ServiceCollection();
var opt = new DbContextOptionsBuilder<Application>().UseSqlite("Data Source=MyDatabase.db");
service.AddDbContextPool<ApplicationContext>(options => options = opt);

instead of the following ?

IServiceCollection service= new ServiceCollection();
service.AddDbContextPool<ApplicationContext>(options => options.UseSqlite("Data Source=MyDatabase.db"));

Edit:

Error message:

System.InvalidOperationException
  HResult=0x80131509
  Message=No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
  Source=Microsoft.EntityFrameworkCore
  StackTrace:
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.GetRelationalService[TService](IInfrastructure`1 databaseFacade)
   at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade)
....
c#
entity-framework-core
asked on Stack Overflow Feb 5, 2018 by Kim Jong Un • edited Feb 5, 2018 by Kim Jong Un

3 Answers

2

Here, (options => options = opt) just works like a regular method:

private void Method(TypeOfParameter options)
{
    options = opt;
}

Here, the options variable is just overwritten. Nothing happens outside of the method. The variable that was used to call the method is not changed. That is why the assignment is useless and has no effect whatsoever.

answered on Stack Overflow Feb 5, 2018 by Patrick Hofman
1

It's because AddDbContextPool accepts an Action as parameter. This action in turn accepts an object of type DbContextOptionsBuilder. This action will be called by framework at some point and the framework will pass to this action an instance of the Builder that it created with some internal rules and tricks. You are supposed to further work with this object, not redefine it.

If you do the assignement you effectively overwrite the object created by framework with your own, which the framework knows nothing about. So all the internal logic of object creation, internal plumbing etc. is lost.

answered on Stack Overflow Feb 5, 2018 by Maxim Zabolotskikh • edited Feb 5, 2018 by Maxim Zabolotskikh
0

The following code roughly simulates what the accepted answer means.

using System;


class DbContextOptionBuilder
{
    public string ConnectionString { get; set; }
    public override string ToString() => $"ConnectionString: {ConnectionString}";
}

class ServiceCollection
{
    public void AddDbContext(Action<DbContextOptionBuilder> job)
    {
        DbContextOptionBuilder o = new DbContextOptionBuilder { ConnectionString = "Empty" };
        job?.Invoke(o);
        Console.WriteLine(o);
    }
}

class Program
{
    static void Wrong(DbContextOptionBuilder o)
    {
        o = new DbContextOptionBuilder { ConnectionString = "SQLITE" };
    }

    static void Correct(DbContextOptionBuilder o)
    {
        o.ConnectionString = "SQLITE";
    }

    static void Main(string[] args)
    {
        ServiceCollection services = new ServiceCollection();
        services.AddDbContext(Wrong);
        services.AddDbContext(Correct);
    }
}
answered on Stack Overflow Feb 5, 2018 by Kim Jong Un

User contributions licensed under CC BY-SA 3.0