Display Name
Display Name

Reputation: 15111

Why cannot I set DbContextOptions with = operator?

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)
....

Upvotes: 1

Views: 856

Answers (3)

Display Name
Display Name

Reputation: 15111

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);
    }
}

Upvotes: 0

Maxim Zabolotskikh
Maxim Zabolotskikh

Reputation: 3367

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.

Upvotes: 1

Patrick Hofman
Patrick Hofman

Reputation: 157048

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.

Upvotes: 2

Related Questions