简体   繁体   中英

Is there a way to set up an Entity Framework Core DbContext with a connection factory?

When creating an Entity Framework Core DbContext against a SQL Server it seems you have three options, provide a connection string to one overload of the DbContextOptionsFactoryExtension method UseSqlServer, a DbConnection directly to another (jackpot? Right - well wait), or to try and go with a DbContextFactory.

I was wondering though, what if you like me have a connection factory configured in DI that you would like EfCore to use? How do you hook that up? Basically I need something that either lets me register some class that I can hook up through DI, or at least a Func<IServiceProvider, IDbConnection> or even Func<IServiceProvider, string> so that I can resolve my factory and create a resilient connection or at least go on the network and fetch fresh creds.

In a cloud solution where you want to have your credentials autorotating in the KeyVault/Secrets Manager/what have you - but where every single access costs money, so you want to use what's cached until the day the creds are rotated where you automatically query the vault for fresh creds and try again.

Same thing if s#,t hits the fan and the database has been restored (as "restore" means "a new database has been created with the old data from the original database" these days). so either way - you need to refresh your config, Since I use Dapper elsewhere, I already have such a cloud ready connection factory already. I just want to use it form Entity Framework too.

Basically - I don't know the correct connection string for sure at ConfigureServices time- so I can't even just create a connection here. I would need some kind of services.AddTransient<IDbConnectionThing>(sp => sp.GetService<CoolFactory>().CreateInstance()); to defer either getting a correct connection string or ideally creating a connection that I have verified to be working - to when the IServiceProvider instance has been constructed.

I'm happy with any workaround that lets me ask the vault for fresh creds, if the connection factory idea is too wild and crazy, but I can't find a way to get to do async things and return a fresh connection string while registering the EF connection string, without doing a super global method sync-over-async meaning David Fowler will sense a disturbance in the Force.

Docs: https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.sqlserverdbcontextoptionsextensions.usesqlserver?view=efcore-5.0#Microsoft_EntityFrameworkCore_SqlServerDbContextOptionsExtensions_UseSqlServer_Microsoft_EntityFrameworkCore_DbContextOptionsBuilder_System_Action_Microsoft_EntityFrameworkCore_Infrastructure_SqlServerDbContextOptionsBuilder_ _

Julie Lerman answered this.

The answer is:

  1. Create a new class that inherits DbConnectionInterceptor, specifically ooverride both ConnectionOpening/ConnectionOpeningAsync (I should never use the sync version, but I don't want this to be the way I find out if I messed up somewhere).
  2. Register the interceptor in the AddDbContext section in Startup.cs:
 services.AddSingleton<AConnectionInterceptor>();
 services.AddDbContext<ADbContext>((provider, options) =>
 {
    options.UseSqlServer(pointlessConnectionString);
    options.AddInterceptors(provider.GetRequiredService<AConnectionInterceptor>());
 });

I refactored out the guts of my factory to do the work on an existing connection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM