c# – 创建一个从用户机密获取连接字符串的DbContextFactory

c# – 创建一个从用户机密获取连接字符串的DbContextFactory,第1张

概述使用WebApi项目和包含实体框架实现的单独数据项目处理DotNetCore解决方案.我们一直在升级库,所以我们使用了所有最新的Core. 在Data项目中,我们创建了一个ApplicationDbContextFactory来创建迁移(需要一个无参数构造函数).由于添加迁移时无参数构造函数约束,您无法注入IOptions<>轻松访问appsettings.json值.我们最终使用Configur 使用WebAPI项目和包含实体框架实现的单独数据项目处理DotNetCore解决方案.我们一直在升级库,所以我们使用了所有最新的Core.

在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的程序包管理器控制台中收到错误?

解决方法 你发布它已经很久了,但我刚刚发现了这个错误,并找出了原因(尽管没有意义)

问题就在于此

console.Write($"CONNECTION STRING: {connectionString}" + Environment.Newline);

如果你在CONNECTION STRING之后将冒号移开它就可以了.我不知道为什么插值中的冒号导致了这个错误

总结

以上是内存溢出为你收集整理的c# – 创建一个从用户机密获取连接字符串的DbContextFactory全部内容,希望文章能够帮你解决c# – 创建一个从用户机密获取连接字符串的DbContextFactory所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1227295.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存