简体   繁体   English

有没有办法使用连接工厂设置实体框架核心 DbContext?

[英]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.在针对 SQL 服务器创建 Entity Framework Core DbContext 时,您似乎有三个选项,提供一个连接字符串到 DbContextOptionsFactoryExtension 方法 UseSqlServer 的一个重载,一个 DbConnection 直接到另一个(大奖?对 - 等等),或者尝试和 Z34D1F91FB2E514B8576FAB1A75A89A6B使用 DbContextFactory。

I was wondering though, what if you like me have a connection factory configured in DI that you would like EfCore to use?不过我想知道,如果您像我一样在 DI 中配置了一个您希望 EfCore 使用的连接工厂怎么办? 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.基本上我需要一些可以让我注册一些 class 的东西,我可以通过 DI 连接,或者至少一个 Func<IServiceProvider, IDbConnection> 甚至 Func<IServiceProvider, string> 以便我可以解析我的工厂并创建一个弹性连接或网络上至少有 go 并获取新的信用。

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.在云解决方案中,您希望您的凭据在 KeyVault/Secrets Manager/您拥有什么 - 但每次访问都需要花钱,因此您希望使用缓存的内容,直到您自动查询凭据的那一天保险库以获得新的信用,然后再试一次。

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).如果 s#,t 击中风扇并且数据库已恢复(因为“恢复”意味着“现在已使用原始数据库中的旧数据创建了一个新数据库”),则同样的事情。 so either way - you need to refresh your config, Since I use Dapper elsewhere, I already have such a cloud ready connection factory already.所以无论哪种方式 - 你需要刷新你的配置,因为我在其他地方使用 Dapper,我已经有了这样一个云就绪连接工厂。 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.基本上 - 我在 ConfigureServices 时不确定正确的连接字符串 - 所以我什至不能在这里创建一个连接。 I would need some kind of services.AddTransient<IDbConnectionThing>(sp => sp.GetService<CoolFactory>().CreateInstance());我需要某种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.推迟获得正确的连接字符串或理想情况下创建我已验证可以正常工作的连接 - 到构造 IServiceProvider 实例时。

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.如果连接工厂的想法过于疯狂和疯狂,我对任何能让我向保险库索取新凭据的解决方法感到满意,但我无法找到一种方法来执行异步操作并在注册时返回新的连接字符串EF 连接字符串,没有执行超级全局方法 sync-over-async,这意味着 David Fowler 会感觉到 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_ _文档: https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.sqlserverdbcontextoptionsextensions.usesqlserver?view=efcore-5.0#Microsoft_EntityFrameworkCore_SqlServerDbContextOptionsExtensions_UseSqlServer_Microsoft_EntityFrameworkCore_DbContextOptionsBuilder_Infrastructure_Action_MicrosoftDbContextOptionsBuilder_Instruction_Action_MicrosoftDb

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).创建一个继承 DbConnectionInterceptor 的新 class,特别是覆盖 ConnectionOpening/ConnectionOpeningAsync (我不应该使用同步版本,但我不希望这成为我发现我是否在某处搞砸的方式)。
  2. Register the interceptor in the AddDbContext section in Startup.cs:在 Startup.cs 的 AddDbContext 部分注册拦截器:
 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.我重构了工厂的内部结构,以便在现有连接上完成工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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