c# – 创建一个从用户机密获取连接字符串的DbContextFactory
使用WebApi项目和包含实体框架实现的单独数据项目处理DotNetCore解决方案.我们一直在升级库,所以我们使用了所有最新的Core.
在Data项目中,我们创建了一个ApplicationDbContextFactory来创建迁移(需要一个无参数构造函数).由于添加迁移时无参数构造函数约束,您无法注入IOptions<>轻松访问appsettings.json值.我们最终使用ConfigurationBuilder来引入WebApi的appsettings.json文件. 我们最近更改了ApplicationDbContextFactory以引入用户机密.这允许每个开发人员使用自定义连接字符串,而不必忽略文件或记住不提交某些内容. 自从进行此更改后,使用dotnet ef迁移添加MIGRATION_NAME在命令行中运行正常.但是,在Visual Studio的程序包管理器控制台中使用添加迁移MIGRATION_NAME现在似乎已被破坏,并显示以下错误:
我尝试了一些命令的变体,看它是否需要指定上下文(除其他外),但似乎没有任何东西绕过这个错误.它似乎永远不会超过ApplicationDbContextFactory中的构造函数. 这是我所指的代码: using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; using Models.Domain.Settings; using System; using System.Diagnostics; namespace Data { public class ApplicationDbContextFactory : IDbContextFactory<ApplicationDbContext> { private readonly SolutionSettings _settings; // In order to use 'add-migration' in Visual Studio,you have to have a parameterless constructor. // Otherwise you get "No parameterless constructor defined for this object." when creating a migration. public ApplicationDbContextFactory() { } public ApplicationDbContextFactory(IOptions<SolutionSettings> settings) { _settings = settings.Value; } public ApplicationDbContext Create(DbContextFactoryOptions options) { // If the IOptions signature was hit,we can just pull the dbconnection from settings if (_settings != null && _settings.DbConnection != null) { var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>() .UseSqlServer(_settings.DbConnection,opts => { opts.EnableRetryOnFailure(); opts.MigrationsAssembly("Data"); }); return new ApplicationDbContext(optionsBuilder.Options); } else { // Otherwise,we have to get the settings manually... return Create(options.ContentRootPath,options.EnvironmentName); } } private ApplicationDbContext Create(string basePath,string environmentName) { // HACK: To pull from WebApiappsettings.json basePath = basePath.Replace("Data","WebApi"); Console.Write($"PATH & ENV: {basePath},{environmentName}" + Environment.NewLine); // Pull in the WebApiappsettings.json files,apply user secrets var builder = new ConfigurationBuilder() .SetBasePath(basePath) .AddJsonFile("appsettings.json",optional: false,reloadOnChange: true) .AddJsonFile($"appsettings.{environmentName.ToLower()}.json",optional: true,reloadOnChange: true) // This needs to match the UserSecretsId value in the WebApi.csproj // Also added a UserSecretsId key with the same value to Data.csproj to suppress a warning // Adding this was the only way it would actually override values with user-secret values .AddUserSecrets("USER_SECRETS_ID") .AddEnvironmentVariables(); var config = builder.Build(); var connectionString = config["SolutionSettings:DbConnection"]; Console.Write($"CONNECTION STRING: {connectionString}" + Environment.NewLine); return Create(connectionString); } private ApplicationDbContext Create(string connectionString) { if (string.IsNullOrEmpty(connectionString)) throw new ArgumentException( $"{nameof(connectionString)} is null or empty.",nameof(connectionString)); var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>() .UseSqlServer(connectionString,options => { options.EnableRetryOnFailure(); options.MigrationsAssembly("Data"); }); return new ApplicationDbContext(optionsBuilder.Options); } } } 作为旁注;在排除故障时我添加了opts.EnableRetryOnFailure();和opts.MigrationsAssembly(“Data”);,但我不知道它们在这个上下文中有任何区别. 我的问题: >这最初是在RC的RC时代实施的,可能有点过时了.创建迁移时是否有更好的方法来完成提取用户机密值?像这样使用工厂仍然是一件事吗? 解决方法
你发布它已经很久了,但我刚刚发现了这个错误,并找出了原因(尽管没有意义)
问题就在于此 console.Write($"CONNECTION STRING: {connectionString}" + Environment.NewLine); 如果你在CONNECTION STRING之后将冒号移开它就可以了.我不知道为什么插值中的冒号导致了这个错误 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |