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

2024-06-30

使用 DotNetCore 解决方案WebApi项目和一个单独的Data包含实体框架实现的项目。我们一直在升级库,因此我们使用所有最新的核心内容。

In the Data项目,我们创建了一个ApplicationDbContextFactory为了创建迁移(需要无参数构造函数)。由于添加迁移时无参数构造函数约束,无法注入IOptions<>轻松访问appsettings.json价值观。我们最终使用了ConfigurationBuilder拉入WebApi's appsettings.json文件。

我们最近改变了ApplicationDbContextFactory也拉进来user-secrets。这允许每个开发人员使用自定义连接字符串,而不必忽略文件或记住不要提交某些内容。

自从进行此更改以来,使用dotnet ef migrations add MIGRATION_NAME在命令行中工作得很好。然而,使用add-migration MIGRATION_NAMEVisual Studio 的包管理器控制台中的程序现在似乎已损坏,并出现以下错误:

add-migration :使用“1”个参数调用“Substring”时出现异常: “StartIndex 不能小于零。参数名称:startIndex”处 行:1 字符:1 + 添加迁移测试 + ~~~~~~~~~~~~~~~~~~~~~~ + 类别信息:未指定:(:) [添加迁移]、MethodInitationException +FullyQualifiedErrorId:ArgumentOutOfRangeException,添加迁移

我尝试了该命令的一些变体,看看它是否需要指定上下文(除其他外),但似乎没有什么可以解决这个错误。它似乎永远不会通过构造函数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(); and opts.MigrationsAssembly("Data");,但我不知道它们在这种情况下有什么区别。

我的问题:

  • 这最初是在 Core 的 RC 时代实现的,可能有点过时了。在创建迁移时是否有更好的方法来完成提取用户机密值?这样用工厂还有事吗?
  • 有人知道为什么我们会在 Visual Studio 的包管理器控制台中收到该错误吗?

自从你发布它以来已经很长时间了,但我刚刚遇到了这个错误并找出了原因(尽管它没有任何意义)

问题就出在这条线上

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

如果删除 CONNECTION STRING 之后的冒号,它就可以工作。 我不知道为什么插值中的冒号会导致此错误

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建一个从用户机密获取连接字符串的 DbContextFactory 的相关文章

随机推荐

  • 基于 R 中多个现有列的计算的新列

    R df orginal 中的原始数据框 AB CD EF GH A 0 12 M A 0 13 F A 0 14 F A 1 16 M A 1 17 F A 1 18 M A 1 18 M A 2 0 78 M A 2 0 12 M A
  • C++ 局部变量销毁顺序

    C 11 中是否存在局部变量释放的定义顺序 更简洁地说 同一作用域中两个局部变量的析构函数的副作用将以什么顺序变得可见 e g struct X X do something int main X x1 X x2 return 0 Is x
  • picamera v2 帧率有限

    关于 picamera v2 帧速率的问题 根据文档picamera http picamera readthedocs io en release 1 12 fov html 以下帧速率对于该硬件是可行的 Resolution Aspec
  • 检查元素是否确实对用户可见

    我想检查用户是否可以在不滚动的情况下看到当前网络浏览器视图中的元素 我发现可以检查该元素是否位于页面上的某个位置 另一个提示建议检查元素位置 但随后我需要获取浏览器可见窗口的尺寸及其x y偏移到0 0 如果有人能给我指出一个不需要 Java
  • 使用 Volley 发送带有 JSON 数据的 POST 请求

    我想发送一个新的JsonObjectRequest要求 我想接收 JSON 数据 来自服务器的响应 好的 我想通过此请求将 JSON 格式的数据发送到服务器 JsonObjectRequest request new JsonObjectR
  • ggplot2:使用 geom_bar 绘制平均值

    我有以下数据框 test2 lt data frame groups c rep group1 4 rep group2 4 X2 c rnorm 4 rnorm 4 label c rep 1 2 rep 2 2 rep 1 2 rep
  • Java错误:不是一个语句,我不知道为什么?

    我真的不确定是什么导致发生这个编译时错误 我一直在试图弄清楚 但似乎找不到问题所在 ClassTable java 253 error not a statement class c class classes nextElement Cl
  • 即使指定了标头,g++ 也找不到标头

    所以基本上我有一些非常简单的代码 其中包括
  • Java客户端找不到主节点:MasterNotDiscoveredException等待[1m]

    我正在使用 vagrant 并使用 debian 软件包在其上安装了 ES elasticsearch 1 1 1 deb 在我的网络应用程序中 我使用 jar org elasticsearch elasticsearch 1 1 1 我
  • 相比之下,超出了最大递归深度

    我写了这段代码来计算组合的数量 def fact n return 1 if n 1 else n fact n 1 def combinations n k return fact n fact n k fact k while True
  • WCF 数据契约和参考实体数据?

    征求有关 最佳 模式的反馈 选项 评论 以用于我的服务中的参考数据 参考数据是什么意思 让我们以北风为例 订单与数据库中的客户相关 当我实现订单服务时 在某些情况下 我希望从订单中引用 完整 客户 而在其他情况下 我只想引用客户 例如键 值
  • Twitter Bootstrap:按钮下拉列表中的图标

    Here http jsfiddle net DjHyQ 是 jsfiddle 上的链接 其中包含一些演示 它在 Chrome 甚至 IE 中运行良好 但在 FF 中图标会下降 我怎样才能解决这个问题而不用负边距或类似的东西来提升它们 我不
  • Asp.net Mvc自定义机制处理未授权请求

    对于我的网站 我希望安全控制器 或操作 具有以下行为 如果用户发出正常请求重定向到登录页面 我可以轻松做到 如果请求是Ajax类型Request IsAjaxRequest true 返回状态码401 我如何为此创建一个过滤器 public
  • 规划带有透明覆盖图像的科尔多瓦相机插件

    我正在编写和应用程序 需要在相机上显示透明图像 例如作为构图指南 该应用程序必须至少在 iOS 和 Android 上发布 到目前为止 我已经找到了一个具有功能 iOS 源的插件 okstate plugin camera overlay
  • 带 null 检查的 Groovy 字符串连接

    有一个更好的方法吗 笔记 part1 part2 and part3是在其他地方定义的字符串变量 它们可以为空 def list part1 part2 part3 list removeAll null def ans list join
  • main() 是用户定义函数吗? [复制]

    这个问题在这里已经有答案了 程序员does定义内部发生的事情main 毕竟 那么 它应该被视为用户定义的函数吗 C 标准没有用户定义函数的概念 相反 它有一个概念库函数 main 不是库函数 但是 该标准还对其签名提出了一些要求 并且不得重
  • Hibernate 过滤器仅在从数据库加载数据后应用吗?

    我在网上发现了一些相互矛盾的信息 有谁知道Hibernate过滤器是否影响生成的sql 或者只是过滤从数据库读取的数据 休眠过滤器影响 where 子句生成的 SQL The Hibernate 过滤器简介 http java dzone
  • 具有无关访问的哈希值

    我有一个非 Rails 项目 在其中从 YAML 文件加载一些设置 config YAML load File open LOG ROOT config database yml 我只能像这样访问这个哈希值config host confi
  • 使用 useStats.getTotalTimeInForeground() 获取设备中每个应用程序在前台花费的时间

    我想知道 Android 设备中运行的所有应用程序所花费的时间 我使用以下代码获取所有包名称 请指导我如何链接包和上述方法来获取应用程序花费的时间 这是代码 List
  • 创建一个从用户机密获取连接字符串的 DbContextFactory

    使用 DotNetCore 解决方案WebApi项目和一个单独的Data包含实体框架实现的项目 我们一直在升级库 因此我们使用所有最新的核心内容 In the Data项目 我们创建了一个ApplicationDbContextFactor