user602291
user602291

Reputation: 155

.Net Core passing connection string to DBContext class

Just started using .Net Core and facing passing connection string information to Context console project.

I have 4 projects, created using .Net Core.

  1. MVC
  2. Service Layer
  3. Domain Layer
  4. Data Layer

In MVC project, I have Startup.cs file where i am reading appsettings.json file

    public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddApplicationInsightsTelemetry(Configuration);

            services.AddMvc();

            // Add appsettings
            services.Configure<AppSettingsConfig>(Configuration.GetSection("AppSettings")); 
}


public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();

        if (env.IsDevelopment())
        {
            // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
            builder.AddApplicationInsightsSettings(developerMode: true);
        }
        Configuration = builder.Build();
    }

In my 4th project (Data Layer), which Console Project and having following DBContext class. This project doesn't have Startup.cs as i MVC project having. Not created by default by VS 2015.

public class MyDWContext : DbContext
{
    public MyDWContext() : base ()
    {

    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);


    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {            
        optionsBuilder.UseSqlServer(@"Data Source=localhost;Initial Catalog=MyDW; Persist Security Info = False; User ID = TempUser; Password = Temp123");
    }

    public DbSet<User> Users { get; set; }
    public DbSet<Class> Classs { get; set; }
}

I have been to other post as well but i believe its created using older version or RC version. So some time i cannot find correct object or .Net classes.

As i have connection string is in MVC project, how can i use connection string during my MVC call to Data layer.

I have Web.API (Core) project as well and that having own connection string (different user configuration in connection string which having only read access). How can i use Web2.API connection string when i am making call from Web2.API project.

Upvotes: 5

Views: 8854

Answers (1)

adem caglin
adem caglin

Reputation: 24153

Instead of passing connection string to DbContext, configuring DbContext in Startup.cs(if possible) is better way. See official docs to understand how to configure DbContext and use it via Dependency Injection.

EDIT : Below code is not good way

However, if you want to pass connection string to DbContext you can use options pattern.

Here is an example how to pass connection string with options pattern:

First you need an options class which accessible from Data Layer and MVC layer

public class ConnectionStringOption
{
     public string ConStr { get ; set; }
}

Then set option value

public void ConfigureServices(IServiceCollection services)
{
     services.AddOptions();
     services.Configure<ConnectionStringOption>(options=>
     {
         // set connection string from configuration  
         options.ConStr = Configuration.GetConnectionString("Default");
     });      
}

appsetting.json

{
  "ConnectionStrings": {
    "Default": "<your connection string>"
  }
}

Finally DbContext

    private readonly IOptions<ConnectionStringOption> _conStrOptions;

    protected YourDbContext()
    {
    }
    public YourDbContext(IOptions<ConnectionStringOption> conStrOptions, DbContextOptions options) 
        : base(options)
    {
        _conStrOptions= conStrOptions;
    }

Edit for another way

Using Static Service Locator may be a solution:

Create a DependencyResolver in Data Layer

public static class DependencyResolver
{
    private static IServiceProvider _provider;
    public static IServiceProvider ServiceProvider
    {
        get
        {
            return _provider;
        }
        set
        {
            if(_provider == null)
            {
                _provider = value;
            }
        }
    }
}

In ConfigureServices method

    public void ConfigureServices(IServiceCollection services)
    {
        // other stuff
        services.AddOptions();
        services.Configure<ConnectionStringOption>(options=>
        {
            // set connection string from configuration  
            options.ConStr = Configuration.GetConnectionString("Default");
        }); 
        DependencyResolver.ServiceProvider = services.BuildServiceProvider();
    }

And finally get option:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{            
    var conStr = DependencyResolver.ServiceLocator.GetService<IOptions<ConnectionStringOption>>().Value.ConStr;
    optionsBuilder.UseSqlServer();
}

Final Edit for previous stupid way

public static class ConnectionStringGetter
{
    public static string ConStr{get;set;}
}

public Startup(IHostingEnvironment env)
{
    //...
    Configuration = builder.Build();
    ConnectionStringGetter.ConStr =  Configuration.GetConnectionString("Default");
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{            
    optionsBuilder.UseSqlServer(ConnectionStringGetter.ConStr);
}

Upvotes: 5

Related Questions