locked
Startup class - change a value during "regular" runtime RRS feed

  • Question

  • User1668405831 posted

    Hi all,

    Wondering if someone knows the answer to this,
    Is it possible for code in Startup - ConfigureServices, Configure, etc. to ever be called again later, after the very first time the application starts up?
    Let's say, when my web application starts up, I set a connection string in ConfigureServices (using services.AddTransient), which will later be injected into different classes making DB calls.

    A few hours later, for whatever reason, the connection string being used by those classes needs to change. Can code execution somehow be sent back into the Startup - ConfigureServices, to run the same code and pick up a new connection string (from the same storage, where the value is updated)?

    So that the same process can happen again - using Dependency Injection, the relevant classes make use of the new connection string, and proceed as before.

    Thanks

    Friday, March 26, 2021 4:59 PM

Answers

  • User1312693872 posted

    Hi,simplify3000

    When the application is running, you can't change the ConfigureServices.

    Do you want to change the connectionstrings during the runtime? You can use DbContextFactory as a workaround, you can select which

    database to use, here is an example:

    public static class DbContextFactory
    {
        public static Dictionary<string, string> ConnectionStrings { get; set; }
    
        public static void SetConnectionString(Dictionary<string, string> connStrs)
        {
            ConnectionStrings = connStrs;
        }
    
        public static MyDbContext Create(string connid)     //judge which connectionstring to use by connid, from Configure()
        {
            if (!string.IsNullOrEmpty(connid))
            {
                var connStr = ConnectionStrings[connid];
                var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
                optionsBuilder.UseSqlServer(connStr);
                return new MyDbContext(optionsBuilder.Options);
            }
            else
            {
                throw new ArgumentNullException("ConnectionId");
            }
        }
    }

    In Configure():

    Dictionary<string, string> connStrs = new Dictionary<string, string>();
    connStrs.Add("DB1", "Server=***;Database=***;***;MultipleActiveResultSets=true");
    connStrs.Add("DB2", Your connection string);
    DbContextFactory.SetConnectionString(connStrs);

    To use:

    if(***)
    {
    var dbContext = DbContextFactory.Create("DB1");
    //such as: var model=dbContext.Models.Tolist();
    //...... }

    Best Regards,

    Jerry Cai

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, March 29, 2021 8:56 AM

All replies

  • User475983607 posted

    The startup code runs once when the application starts.  So, just restart the application when the connection string changes.  Can you explain why the connection string changes?  Usually, the connection strings do not change.  Can you explain your requirement rather than the solution?

    Friday, March 26, 2021 5:02 PM
  • User1668405831 posted

    Hi mgebhard - 

    The connection strings (i.e. passwords), change without notice due to company security policies.
    When that happens, we actually don't want to restart the application, if at all possible.
    Since users would be getting errors in the meantime.

    So the requirement is to pick up a new connection string as soon as it changes, minimize user errors and manual restarts.
    While still using the usual DI mechanism... that's why I was thinking of calling ConfigureServices again when that happens.

    thanks

    Friday, March 26, 2021 6:33 PM
  • User475983607 posted

    The connection strings (i.e. passwords), change without notice due to company security policies.
    When that happens, we actually don't want to restart the application, if at all possible.
    Since users would be getting errors in the meantime.

    I usually run web application under a service account and use integrated security.  I know the when passwords expire and can setup a service windows far ahead of time.  

    So the requirement is to pick up a new connection string as soon as it changes, minimize user errors and manual restarts.  While still using the usual DI mechanism... that's why I was thinking of calling ConfigureServices again when that happens.

    You can lookup the connection string on the fly when a scoped context is created.  It's just a matter of writing a little lookup utility and following a coding standard going forward.  

    Friday, March 26, 2021 7:46 PM
  • User-474980206 posted

    If you are using asp.net core you can use option snapshot to achieve this.

    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-5.0

    Saturday, March 27, 2021 3:23 PM
  • User1312693872 posted

    Hi,simplify3000

    When the application is running, you can't change the ConfigureServices.

    Do you want to change the connectionstrings during the runtime? You can use DbContextFactory as a workaround, you can select which

    database to use, here is an example:

    public static class DbContextFactory
    {
        public static Dictionary<string, string> ConnectionStrings { get; set; }
    
        public static void SetConnectionString(Dictionary<string, string> connStrs)
        {
            ConnectionStrings = connStrs;
        }
    
        public static MyDbContext Create(string connid)     //judge which connectionstring to use by connid, from Configure()
        {
            if (!string.IsNullOrEmpty(connid))
            {
                var connStr = ConnectionStrings[connid];
                var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
                optionsBuilder.UseSqlServer(connStr);
                return new MyDbContext(optionsBuilder.Options);
            }
            else
            {
                throw new ArgumentNullException("ConnectionId");
            }
        }
    }

    In Configure():

    Dictionary<string, string> connStrs = new Dictionary<string, string>();
    connStrs.Add("DB1", "Server=***;Database=***;***;MultipleActiveResultSets=true");
    connStrs.Add("DB2", Your connection string);
    DbContextFactory.SetConnectionString(connStrs);

    To use:

    if(***)
    {
    var dbContext = DbContextFactory.Create("DB1");
    //such as: var model=dbContext.Models.Tolist();
    //...... }

    Best Regards,

    Jerry Cai

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, March 29, 2021 8:56 AM
  • User753101303 posted

    Hi,

    The connection strings (i.e. passwords), change without notice due to company security policies.
    When that happens, we actually don't want to restart the application, if at all possible.

    You need to change the password "by hand" before restarting the application? By using https://www.mssqltips.com/sqlservertip/5340/using-group-managed-service-accounts-with-sql-server/ you should be able to use a Windows account whose password is changed automatically without any manual action.

    Monday, March 29, 2021 9:02 AM
  • User1668405831 posted

    Hello all,

    It looks like I will have to re-work my application a bit more than I was hoping for.
    But it is great to have these suggestions.
    Thank you very much for your replies,

    Tuesday, March 30, 2021 7:32 PM