更改 IdentityServer4 实体框架表名称

2024-05-09

我正在尝试更改由 IdentityServer4 的 PersistedGrantDb 和 ConfigurationDb 创建的默认表名称,并让实体框架生成正确的 SQL。例如;而不是使用实体IdentityServer4.EntityFramework.Entities.ApiResource使用表格ApiResources,我希望将数据映射到名为的表中mytesttable

根据文档 https://learn.microsoft.com/en-us/ef/core/modeling/relational/tables这应该像添加一样简单ToTable对我想要在中重新映射的每个实体的调用DBContext's OnModelCreating方法来覆盖 TableName = EntityName 的默认行为。问题是这确实创建了一个表mytesttable但实体框架在运行时创建的 SQL 仍然使用ApiResources在查询中,因此失败。

我采取的步骤是我创建了一个DBContext源自 IdentityServer 的ConfigurationDbContext为了能够覆盖OnModelCreating并自定义表名称:

public class MyTestDbContext : ConfigurationDbContext
{
    public MyTestDbContext(DbContextOptions<ConfigurationDbContext> options, ConfigurationStoreOptions storeOptions) : base(options, storeOptions)
    { }


    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {

        Console.WriteLine("OnModelCreating invoking...");

        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<IdentityServer4.EntityFramework.Entities.ApiResource>().ToTable("mytesttable");

        base.OnModelCreating(modelBuilder);

        Console.WriteLine("...OnModelCreating invoked");
    }
}

我还实现了一个DesignTimeDbContextFactoryBase<MyTestDBContext>类来制造MyTestDbContext在设计时通过调用时的实例dotnet ef migrations命令行语法。

这有效并调用dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c MyTestDbContext -o Data/Migrations/IdentityServer/MyTestContext在我的程序集中创建初始迁移。

然后我启动 IdentityServer 实例,调用测试方法Startup包含以下逻辑:

private static void InitalizeDatabase(IApplicationBuilder app)
{
        using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
         {

            serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();

            var context = serviceScope.ServiceProvider.GetRequiredService<MyTestDbContext>();
            context.Database.Migrate();

            /* Add some test data here... */
        }
}

这愉快地漫游并使用在我的 PostGRES 数据库中创建必要的表NpgSQL提供者,包括名为的表mytesttable代替ApiResources对于实体IdentityServer4.EntityFramework.Entities.ApiResource。但是,当我从 IdentityServer 实例调用命令时,生成的 SQL 仍然引用ApiResources代替mytesttable:

  Failed executing DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
  SELECT x."Id", x."Description", x."DisplayName", x."Enabled", x."Name"
  FROM "ApiResources" AS x
  ORDER BY x."Id"
  Npgsql.PostgresException (0x80004005): 42P01: relation "ApiResources" does not exist

任何帮助表示赞赏。


这个答案有两个部分;首先需要在 IdentityServer 的配置中调整表名称,以便它使用新的表名称生成查询。第二;需要修改实体框架生成的模式,以便它知道为身份框架实体创建不同名称的表。继续阅读...

所以,首先;更改实体框架查询中使用的表名称的能力公开在AddOperationalStore and AddConfigurationStore挂起的方法AddIdentityServer中间件方法。这options提供给配置方法的委托参数公开表名称,例如:options.{EntityName}.Name = {WhateverTableNameYouWantToUse} - or options.ApiResource.Name = mytesttable。您还可以通过调整每个表的基础来覆盖架构Schema财产。

下面的示例使用反射来更新所有实体以使用前缀为的表名idn_, so idn_ApiResources, idn_ApiScopes etc:

services.AddIdentityServer()
.AddConfigurationStore(options => {
                // Loop through and rename each table to 'idn_{tablename}' - E.g. `idn_ApiResources`
                foreach(var p in options.GetType().GetProperties()) {
                if (p.PropertyType == typeof(IdentityServer4.EntityFramework.Options.TableConfiguration))
                {
                    object o = p.GetGetMethod().Invoke(options, null);
                    PropertyInfo q = o.GetType().GetProperty("Name");

                    string tableName = q.GetMethod.Invoke(o, null) as string;
                    o.GetType().GetProperty("Name").SetMethod.Invoke(o, new object[] { $"idn_{tableName}" });
                    
                }
            }

         // Configure DB Context connection string and migrations assembly where migrations are stored  
            options.ConfigureDbContext = builder => builder.UseNpgsql(_configuration.GetConnectionString("IDPDataDBConnectionString"),
                sql => sql.MigrationsAssembly(typeof(IdentityServer.Data.DbContexts.MyTestDbContext).GetTypeInfo().Assembly.GetName().Name));
}
.AddOperationalStore(options => { 

 // Copy and paste from AddConfigurationStore logic above.
}

第二部分是修改实体框架从 IdentityServer 实体生成的模式。要实现这一目标,您有两个选择:您可以从 IdentityServer 提供的 DBContext 之一派生;ConfigurationDbContext or PeristedGrantDbContext然后覆盖OnModelCreating方法将每个 IdentityServer 实体重新映射到修改后的表名称,然后创建初始迁移或更新迁移为记录在这里 https://learn.microsoft.com/en-us/ef/core/modeling/relational/tables(流利的Api语法),or您可以从提供的 IdentityServer DBContext 创建初始迁移ConfigurationDbContext and PersistedGrantDbContext按照教程添加迁移 https://identityserver4.readthedocs.io/en/release/quickstarts/8_entity_framework.html部分,然后使用文本编辑器对所有表名称以及对创建的迁移文件中这些表名称的引用进行查找和替换。

无论您选择哪种方法,您仍然需要使用dotnet ef migrations ...命令行语法用于创建初始迁移文件,如下所示添加迁移 https://identityserver4.readthedocs.io/en/release/quickstarts/8_entity_framework.html或包含表更改的修改集,完成此操作后,运行 IdentityServer 项目,将在目标数据库中创建架构。

Note; OnModelCreating是通过调用dotnet ef migrations语法(也称为设计时)以及运行时(如果您调用)Database.Migrate()在你的 DBContext 上 - 例如MyDbContextInstance.Database.Migrate()(或异步等效方法)。

如果你想使用自定义的DBContext,那么你可以自定义OnModelCreating,您需要添加一些在调用时使用的设计时类dotnet ef从命令行并将新上下文添加到Startup.

为了完整起见,下面是一个 hacky 粗略示例,其中上下文目标是 PostGres 数据库(使用UseSQLServer代替UseNpgsql或者无论您的后备存储是什么(如果不同),连接字符串名称是IDPDataDBConnectionString在 appsettings.json 文件和本例中的自定义数据库上下文中是MyTestDbContext它源自 IdentityServer 的ConfigurationDbContext.

复制粘贴代码,调整路径为appsettings.json(或重构)然后从命令行执行dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c MyTestDbContext -o Data/Migrations/IdentityServer/ConfigurationDbCreatedWithMyTestContext您应该看到实体框架使用您放置的任何覆盖生成架构迁移文件OnModelCreating根据您派生的上下文。下面的例子还包括一些Console.WriteLine调用以更轻松地跟踪正在发生的事情。

将其添加到Startup:

 services.AddDbContext<MyTestDbContext>(options =>
        {
            options.UseNpgsql(_configuration.GetConnectionString("IDPDataDBConnectionString"));
        }); 

Note如果您愿意,使用设计时类还允许您将 IdentityServer 数据库迁移文件分离到单独的类库中。确保您的目标是Startup如果你这样做(参见here https://stackoverflow.com/questions/38705694/add-migration-with-different-assembly了解更多信息)。

namespace MyIdentityServer.DataClassLibrary.DbContexts
{

public class MyTestDbContext : ConfigurationDbContext
{
    public MyTestDbContext(DbContextOptions<ConfigurationDbContext> options, ConfigurationStoreOptions storeOptions) : base(options, storeOptions)
    { }


    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {

        Console.WriteLine("OnModelCreating invoking...");

        base.OnModelCreating(modelBuilder);

        // Map the entities to different tables here
        modelBuilder.Entity<IdentityServer4.EntityFramework.Entities.ApiResource>().ToTable("mytesttable");

        Console.WriteLine("...OnModelCreating invoked");
    }

}
public class MyTestContextDesignTimeFactory : DesignTimeDbContextFactoryBase<MyTestDbContext>
{

    public MyTestContextDesignTimeFactory()
        : base("IDPDataDBConnectionString", typeof(MyTestContextDesignTimeFactory).GetTypeInfo().Assembly.GetName().Name)
    {
    }

    protected override MyTestDbContext CreateNewInstance(DbContextOptions<MyTestDbContext> options)
    {
        var x = new DbContextOptions<ConfigurationDbContext>();

        Console.WriteLine("Here we go...");

        var optionsBuilder = newDbContextOptionsBuilder<ConfigurationDbContext>();

        optionsBuilder.UseNpgsql("IDPDataDBConnectionString", postGresOptions => postGresOptions.MigrationsAssembly(typeof(MyTestContextDesignTimeFactory).GetTypeInfo().Assembly.GetName().Name));

        DbContextOptions<ConfigurationDbContext> ops = optionsBuilder.Options;

        return new MyTestDbContext(ops, new ConfigurationStoreOptions());
    }
}




/* Enable these if you just want to host your data migrations in a separate assembly and use the IdentityServer supplied DbContexts 

public class ConfigurationContextDesignTimeFactory : DesignTimeDbContextFactoryBase<ConfigurationDbContext>
{

    public ConfigurationContextDesignTimeFactory()
        : base("IDPDataDBConnectionString", typeof(ConfigurationContextDesignTimeFactory).GetTypeInfo().Assembly.GetName().Name)
    {
    }

    protected override ConfigurationDbContext CreateNewInstance(DbContextOptions<ConfigurationDbContext> options)
    {
        return new ConfigurationDbContext(options, new ConfigurationStoreOptions());
    }
}

public class PersistedGrantContextDesignTimeFactory : DesignTimeDbContextFactoryBase<PersistedGrantDbContext>
{
    public PersistedGrantContextDesignTimeFactory()
        : base("IDPDataDBConnectionString", typeof(PersistedGrantContextDesignTimeFactory).GetTypeInfo().Assembly.GetName().Name)
    {
    }

    protected override PersistedGrantDbContext CreateNewInstance(DbContextOptions<PersistedGrantDbContext> options)
    {
        return new PersistedGrantDbContext(options, new OperationalStoreOptions());
    }
}
*/

public abstract class DesignTimeDbContextFactoryBase<TContext> :
IDesignTimeDbContextFactory<TContext> where TContext : DbContext
{
    protected string ConnectionStringName { get; }
    protected String MigrationsAssemblyName { get; }
    public DesignTimeDbContextFactoryBase(string connectionStringName, string migrationsAssemblyName)
    {
        ConnectionStringName = connectionStringName;
        MigrationsAssemblyName = migrationsAssemblyName;
    }

    public TContext CreateDbContext(string[] args)
    {
        return Create(
            Directory.GetCurrentDirectory(),
            Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"),
            ConnectionStringName, MigrationsAssemblyName);
    }
    protected abstract TContext CreateNewInstance(
        DbContextOptions<TContext> options);

    public TContext CreateWithConnectionStringName(string connectionStringName, string migrationsAssemblyName)
    {
        var environmentName =
            Environment.GetEnvironmentVariable(
                "ASPNETCORE_ENVIRONMENT");

        var basePath = AppContext.BaseDirectory;

        return Create(basePath, environmentName, connectionStringName, migrationsAssemblyName);
    }

    private TContext Create(string basePath, string environmentName, string connectionStringName, string migrationsAssemblyName)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(basePath)
            .AddJsonFile(@"c:\change\this\path\to\appsettings.json")
            .AddJsonFile($"appsettings.{environmentName}.json", true)
            .AddEnvironmentVariables();

        var config = builder.Build();

        var connstr = config.GetConnectionString(connectionStringName);

        if (String.IsNullOrWhiteSpace(connstr) == true)
        {
            throw new InvalidOperationException(
                "Could not find a connection string named 'default'.");
        }
        else
        {
            return CreateWithConnectionString(connstr, migrationsAssemblyName);
        }
    }

    private TContext CreateWithConnectionString(string connectionString, string migrationsAssemblyName)
    {
        if (string.IsNullOrEmpty(connectionString))
            throw new ArgumentException(
         $"{nameof(connectionString)} is null or empty.",
         nameof(connectionString));

        var optionsBuilder =
             new DbContextOptionsBuilder<TContext>();

        Console.WriteLine(
            "MyDesignTimeDbContextFactory.Create(string): Connection string: {0}",
            connectionString);

        optionsBuilder.UseNpgsql(connectionString, postGresOptions => postGresOptions.MigrationsAssembly(migrationsAssemblyName));

        DbContextOptions<TContext> options = optionsBuilder.Options;

        Console.WriteLine("Instancing....");

        return CreateNewInstance(options);
    }
}

}

边注;如果您已经有了一个包含 IdentityServer 表的数据库,您可以手动重命名它们,忽略实体框架迁移 - 您唯一需要的就是更改Startup to AddConfigurationStore and AddOperationalStore.

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

更改 IdentityServer4 实体框架表名称 的相关文章

  • 如何为 MySQL 和 Postgres 编写不区分大小写的查询?

    我在本地运行 MySQL 数据库进行开发 但部署到使用 Postgres 的 Heroku Heroku 处理几乎所有事情 但我不区分大小写的 Like 语句变得区分大小写 我可以使用 iLike 语句 但我的本地 MySQL 数据库无法处
  • 在 C++ 中,std::string::push_back() 的摊余复杂度是 O(1) 吗?

    我知道标准指定它适用于向量 但是字符串呢 是的 它是摊销常数时间 请参见第 716 页的表 101本文件的 http www open std org jtc1 sc22 wg21 docs papers 2012 n3485 pdf 表
  • 是否可以通过引用以基类作为参数的函数来传递派生类

    假设我们有一个抽象基类IBase使用纯虚方法 接口 然后我们推导出CFoo CFoo2来自基类 我们有一个知道如何使用 IBase 的函数 Foo IBase input 这些情况下通常的场景是这样的 IBase ptr static ca
  • 有没有办法让我的程序用更少的代码运行?

    我为学校作业编写了以下代码 它编译并打印所有正确的消息 但出于我自己的好奇心 我想知道我的代码是否可以缩短并且仍然有效 我尝试了 signal 而不是 sigaction 但我听说 sigaction 比 signal 更受青睐 此外 此任
  • 使用 pthread_cond_signal 优雅地终止线程被证明是有问题的

    我需要发射一堆线程 并希望优雅地将它们拉下来 我正在尝试使用pthread cond signal pthread cond wait实现这一目标 但遇到了问题 这是我的代码 首先是thread main static void thrma
  • 通过 EUSART PIC18F45K80 打印消息

    我正在尝试向 Docklight 发送串行消息 但始终收到空值 我正在使用带有 XC8 MPLAB X 的 PIC18F45K80 我的代码中的所有内容似乎都是正确的 但我想我错了 我该如何修复它 include
  • 我可以将特定警告视为错误吗?

    以下是我有时在学生代码中看到的模式的简化版本 bool foobar int a int b if a lt b return true 当然 真正的代码要复杂得多 Visual Studio 报告警告 C4715 并非所有控制路径都会返回
  • REASSIGN OWNED BY 为 1 个指定数据库

    我想使用以下命令更改一个特定数据库中所有表的所有者 REASSIGN OWNED BY postgres TO myuser 但它显示 ERROR cannot reassign ownership of objects owned by
  • 在 C++ 中初始化指针

    可以在声明时将指针分配给值吗 像这样的东西 int p 1000 是的 您可以在声明时初始化指向值的指针 但是您不能这样做 int p 1000 是个地址运算符 并且您不能将其应用于常量 尽管如果可以 那会很有趣 尝试使用另一个变量 int
  • Windows 身份验证失败并显示“401 Unauthorized”

    我有一个 MVC 客户端访问受 IDS4 保护的 Web API 它们都在我的本地计算机上运行并由 IIS 托管 使用本地身份进行身份验证时 该应用程序运行良好 但是 当我尝试使用 Windows 身份验证时 开发工具不断收到 401 Un
  • 在 OpenGL 中使用不同的着色器程序?

    我必须在 OpenGL 中针对不同的对象使用两个不同的着色器程序 我发现我必须使用glUseProgram 在不同的着色器程序之间切换 但对此没有太多信息 鉴于我有两个用于不同对象的不同着色器程序 如何为每个着色器程序生成和绑定 VAO 和
  • C++ 中类型信息何时向后流动?

    我刚刚看了 Stephan T Lavavej 的演讲CppCon 2018关于 类模板参数推导 在哪里某个点 https youtu be H ut6j1BYU t 941他顺便说 在 C 中 类型信息几乎永远不会向后流动 我不得不说 几
  • 如何从 Function App 设置会话 ID 或创建自定义字段到 Application Insights

    功能应用程序如下 public static async Task
  • C# 或 Windows 相当于 OS X 的 Core Data?

    我迟到了 现在才开始在 OS X Cocoa 中使用 Core Data 它令人难以置信 并且确实改变了我看待事物的方式 C 或现代 Windows 框架中是否有等效的技术 即拥有可免费保存 数据管理 删除 搜索的托管数据类型 还想知道Li
  • 如何明智地解释这个编译器警告?

    当我执行这段代码时question https stackoverflow com a 51056490 2411320 我收到这个警告 warning format d expects argument of type int but a
  • 如何正确地将十六进制转义添加到字符串文字中?

    当你有C语言的字符串时 你可以在里面直接添加十六进制代码 char str abcde a b c d e 0x00 char str2 abc x12 x34 a b c 0x12 0x34 0x00 这两个示例在内存中都有 6 个字节
  • 使texture2D在运行时/脚本Unity3D中可读[重复]

    这个问题在这里已经有答案了 我有一个插件 可以让我访问 Android 手机图库中的图片 这给了我一个Texture2D类型的纹理 然后我想使用 GetPixels 函数对其进行编辑 但默认情况下它未设置为可读 如何使纹理可读 以便我可以在
  • 如何在您的网站中连接两个人

    有一款名为 Verbosity 的游戏 这是一款有目的的游戏 位于此链接上www gwap com 在游戏中 他们随机连接两个玩家互相玩 游戏是玩家1应该向他的搭档 玩家2 描述一个单词 而玩家2应该猜测这个单词 我正在尝试建立一个网站来执
  • C# 中的快速字符串解析

    在 C 中解析字符串最快的方法是什么 目前我只是使用字符串索引 string index 并且代码运行合理 但我忍不住认为索引访问器所做的连续范围检查必须添加一些东西 所以 我想知道我应该考虑哪些技术来增强它 这些是我最初的想法 问题 使用
  • 应用非限定名称查找而不是依赖于参数的名称查找

    考虑标准 sec 3 4 1 3 中的一个示例 typedef int f namespace N struct A friend void f A operator int void g A a int i f a f is the ty

随机推荐

  • 为 Python 2.4 改进“with”语句的直接替换

    您能否建议一种方法来编写可在 Python 2 4 中使用的 with 语句的直接替换代码 这将是一个 hack 但它可以让我更好地将我的项目移植到 Python 2 4 EDIT 删除了不相关的元类草图 只需使用 try finally
  • 获取调用表单的名称空间

    我想要一个宏this ns这样它就会返回调用它的位置的名称空间 例如 如果我有这段代码 ns nstest main require nstest core as nstest defn ns str x gt x getName name
  • 如何在 Python 中仅列出 zip 存档中的文件夹?

    如何仅列出 zip 存档中的文件夹 这将列出存档中的每个文件夹和文件 import zipfile file zipfile ZipFile samples sample zip r for name in file namelist pr
  • 在Python中计算结构体的CRC

    我有以下结构 来自 C 中的 NRPE 守护程序代码 typedef struct packet struct int16 t packet version int16 t packet type uint32 t crc32 value
  • Webview 中的 Java 空指针异常

    我试图搜索这个问题 但这个错误看起来与这个错误 https stackoverflow com questions 21866459 android nullpointerexception on webview 我的 google pla
  • 如何减少 JSF 中的 javax.faces.ViewState

    减少 JSF 中视图状态隐藏字段大小的最佳方法是什么 我注意到我的视图状态约为 40k 这会在每次请求和响应时下降到客户端并返回到服务器 特别是到达服务器时 这对用户来说会显着减慢 我的环境 JSF 1 2 MyFaces Tomcat T
  • x11 - 导入错误:没有名为“kivy.core.window.window_x11”的模块

    目前我正在尝试构建一个我通过 buildozer 用 Python 和 Kivy 编写的应用程序 无论我在做什么 我都会遇到 window x11 的问题 即使我在代码中注释掉所有与 Windows 相关的内容或执行本文中描述的所有操作 这
  • Visual Studio - 在哪里定义自定义路径宏?

    我刚刚打开了其他人的 Visual Studio 项目 在他们的构建属性中 他们有一些用于包含和 lib 目录的自定义路径宏 宏名称是这样的 MY WHATEVER INCLUDE DIR 我可以手动将每个宏替换为真实路径 但最好只使用宏
  • 将服务连接到现有的流星帐户

    我正在设置一个流星应用程序 其中涉及使用用户名和密码进行注册 然后希望将该帐户与 Facebook 和 Twitter 连接起来 我只需使用帐户包即可轻松启动并运行第一部分 但是当我有一个登录用户调用 Meteor loginWithFac
  • mysqli_connect(): (HY000/2002): 无法建立连接,因为目标机器主动拒绝

    我知道有很多这样的问题 但我没有找到任何解决方案 我尝试过的事情 检查防火墙 重新启动我的电脑和 Apache 服务器 重新启动MYSQL 检查了我的代码 尝试了我所知道的和在互联网上找到的一切 这是我的代码
  • 在 IIS 托管的 ASP.NET Web 应用程序中打开页面时显示“找不到资源”

    我正在使用 IIS 8 5 将 Web 应用程序 Net 4 5 托管到远程服务器 该应用程序在本地和远程 IIS 上运行良好 但是有一个页面 Reports ReportsMain aspx 导致错误 找不到资源 我确保该页面存在 我还确
  • 在 Java 中打开现有文件并关闭它。

    是否可以在java中打开一个文件附加数据并关闭多次 例如 psuedocode class variable declaration FileWriter writer1 new FileWriter filename fn1 writer
  • 在 Chrome 中检索浏览器语言

    我一直在尝试让 momentjs 正确检测浏览器语言并本地化时间显示 按照使用 Moment js 进行区域设置检测 https stackoverflow com questions 25725882 locale detection w
  • 如何在 Python 中执行相当于预处理器指令的操作?

    有没有办法在 Python 中执行以下预处理器指令 if DEBUG lt do some code gt else lt do some other code gt endif There s debug 这是编译器预处理的特殊值 if
  • 如何将mysql数据库移动到另一个安装点

    我有一个 MySQL 数据库 它变得越来越大 我想将整个数据库移动到另一个安装点 在那里我有足够的存储空间 我希望传输当前数据 并将新数据保存到新位置 软件堆栈 在 FreeBSD 6 上运行的 MySQL 5 当然其他答案也是有效的 但如
  • 如何支持滑动删除具有组合布局的 UICollectionView 列表中的行?

    以前对于表视图 这是在UITableViewDataSource委托回调tableView commit forRowAt 相关 API 中是否有等效功能新的集合视图 https developer apple com documentat
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • PyQt - 如何检查 QDialog 是否可见?

    我有个问题 我有这个代码 balls Ball for i in range 1 10 因此 当我说 Ball 时 这将在 QDialog 上绘制一个球 然后当这完成后 我正在移动球QDialog无限循环中 我想说类似的话while QDi
  • 具有维度的 Amazon Web Service CloudWatch 自定义指标

    我正在尝试将数据推送到 AWS CloudWatch 上的自定义指标 但想了解有关维度的更多信息以及如何使用它们 我已经阅读了 AWS 文档 但它并没有真正解释它们的用途以及它如何影响 AWS 管理控制台中的图形 UI 维度是进一步细分指标
  • 更改 IdentityServer4 实体框架表名称

    我正在尝试更改由 IdentityServer4 的 PersistedGrantDb 和 ConfigurationDb 创建的默认表名称 并让实体框架生成正确的 SQL 例如 而不是使用实体IdentityServer4 EntityF