在Data项目中,我们创建了一个ApplicationDbContextFactory来创建迁移(需要一个无参数构造函数).由于添加迁移时无参数构造函数约束,您无法注入IOptions<>轻松访问appsettings.json值.我们最终使用ConfigurationBuilder来引入WebApi的appsettings.json文件.
我们最近更改了ApplicationDbContextFactory以引入用户机密.这允许每个开发人员使用自定义连接字符串,而不必忽略文件或记住不提交某些内容.
自从进行此更改后,使用dotnet ef迁移添加MIGRATION_NAME在命令行中运行正常.但是,在Visual Studio的程序包管理器控制台中使用添加迁移MIGRATION_NAME现在似乎已被破坏,并显示以下错误:
add-migration : Exception calling “Substring” with “1″ argument(s):
“StartIndex cannot be less than zero. Parameter name: startIndex” At
line:1 char:1 + add-migration TESTING + ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Add-Migration],MethodInvocationException
+ FullyQualifiedErrorId : ArgumentOutOfRangeException,Add-Migration
我尝试了一些命令的变体,看它是否需要指定上下文(除其他外),但似乎没有任何东西绕过这个错误.它似乎永远不会超过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 WebApi\appsettings.json basePath = basePath.Replace("Data","WebApi"); Console.Write($"PATH & ENV: {basePath},{environmentName}" + Environment.NewLine); // Pull in the WebApi\appsettings.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时代实施的,可能有点过时了.创建迁移时是否有更好的方法来完成提取用户机密值?像这样使用工厂仍然是一件事吗?
>任何人都知道我们为什么在Visual Studio的程序包管理器控制台中收到错误?
解决方法
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。