8

I have scenario where I have to expand my project with .NET CORE WEB API PROJECT.

In the beginning it was just console app which was working as a windows service on a simple tasks, adding data from xml files to database.

And my structure looks like this:

  1. Database Project (ENTITY FRAMEWORK CORE)
  2. Console App ( REFERENCING TO DATABASE PROJECT)
  3. Web Api (REFERENCING TO DATABASE PROJECT)

Now when I created WEB API project it requires me to register Context in Startup.cs and I did it like this:

Startup.cs

// DbContext for MSSQL
services.AddDbContextPool<ProductXmlDBContext>(options => options.UseSqlServer(_configuration.GetConnectionString(Config.CONNECTION_STRING)));

And that is all fine.

But now I want to read connection string for console application for it's own connection string (appsettings.json) since when I created API it got his own appsettings.json where I'm storing connection string for WEB API.

My DBContext looks like this:

public ProductXmlDBContext()
{

}
// I added this because it was required for WEB API to work
public ProductXmlDBContext(DbContextOptions<ProductXmlDBContext> options) : base(options)
{

}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(@"Server=localhost;Database=ProductXml;Trusted_Connection=True;");
}

In my console app I have add appsettings.json

enter image description here

And here is my Program.cs:

static void Main(string[] args)
{
    try
    {
        // Set up configuration sources.
        var builder = new ConfigurationBuilder()
            .SetBasePath(Path.Combine(AppContext.BaseDirectory))
            .AddJsonFile("appsettings.json", optional: true);

        var services = new ServiceCollection();

        Configuration = builder.Build();

        // 
        var x = Configuration.GetConnectionString("DefaultConnection");

        services.AddDbContextPool<ProductXmlDBContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
    }
}

And here is how I use Context in my console application:

using (var context = new ProductXmlDBContext())
{
    companies = context.Companies.ToList();
}

And probably because of this usage it uses value from protected override void OnConfiguring method instead from its own appsettings.json ?

So how could I read connection string for this console application only from itself appsettings.json (to remove/avoid using hardcoded value) from context.

Edit:

There is no GetConnectionString option:

enter image description here

Thanks a lot!

Cheers

11
  • 1
    From : optionsBuilder.UseSqlServer(@"Server=localhost;Database=ProductXml;Trusted_Connection=True;"); To : optionsBuilder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")); Commented Jan 3, 2021 at 11:33
  • @jdweng But than which appsettings.json would be used ? Commented Jan 3, 2021 at 11:38
  • The one in the deployed application. Commented Jan 3, 2021 at 11:41
  • A project has only one configuration file which can be xml or json and can be read any place in the code. You need to set the connection string that dbContext will use. The json is accessing the dbContext and not connecting directly to the database. Commented Jan 3, 2021 at 11:41
  • Check net publish. It will copy the application json depending which application you publish Commented Jan 3, 2021 at 11:42

2 Answers 2

5

One option I can suggest is to create another DBContextClass in your console application and just override the OnConfiguring method to read from appsettings of console application project

Example: New Class in Console Application

public class ConsoleProductXmlDBContext : ProductXmlDBContext
    {
        private readonly IConfiguration _iConfiguration;
        private readonly string _connectionString;

        public ConsoleProductXmlDBContext()
        {
            IConfigurationBuilder builder = new ConfigurationBuilder()
                        .SetBasePath(Directory.GetCurrentDirectory())
                        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
            _iConfiguration = builder.Build();
            _connectionString = _iConfiguration.GetConnectionString("DefaultConnection");
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            _ = optionsBuilder.UseSqlServer(_connectionString, providerOptions => providerOptions.CommandTimeout(60))
                          .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
        }
    }

Usage in Console Application

using (var context = new ConsoleProductXmlDBContext())
{
    companies = context.Companies.ToList();
}
Sign up to request clarification or add additional context in comments.

1 Comment

This answer is simpler than it looks and was the right way for my .NET6 console app
0

Check the documentation here: https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.onconfiguring?view=efcore-5.0

In situations where an instance of DbContextOptions may or may not have been passed to the constructor, you can use IsConfigured to determine if the options have already been set, and skip some or all of the logic in OnConfiguring(DbContextOptionsBuilder).

So you can check the IsConfigured value and do nothing if options have been provided already.

The proper solution though, would be to have the overridden function read from the configuration directly, if there is no reason to override it at the first place.

https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/?view=aspnetcore-5.0#publish-to-a-folder The published folder will contain the proper configuration file, depending on which application you published.

2 Comments

Indeed when I run console app it says that IsConfigured is false.. even if I thought that I configured it in Main.cs (code is above). Thanks for help
Mate, how come it's not configured even if I added those settings in Main method of Program.cs ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.