使用FluentNHibernate配置Hangfire连接Oracle时遇ORA-01408错误
在Oracle上配置Hangfire+FluentNHibernate遭遇ORA-01408错误的疑问
我在Oracle数据库(19.17.0.0)上使用FluentNHibernate配置Hangfire时,遇到错误:ORA-01408: such column list already indexed。
我的配置如下:
1. RegisterHangfire.cs
public static void RegisterHangfire( this IServiceCollection serviceCollection, CustomSettings customSettings) { var storage = FluentNHibernateStorageFactory.For( ProviderTypeEnum.OracleClient10Managed, DATABASE_URL, new FluentNHibernateStorageOptions { TransactionIsolationLevel = IsolationLevel.Serializable, QueuePollInterval = TimeSpan.FromSeconds(15), JobExpirationCheckInterval = TimeSpan.FromHours(1), CountersAggregateInterval = TimeSpan.FromMinutes(5), UpdateSchema = true, DashboardJobListLimit = 50000, InvisibilityTimeout = TimeSpan.FromMinutes(15), TransactionTimeout = TimeSpan.FromMinutes(1), JobQueueDistributedLockTimeout = TimeSpan.FromMinutes(1.0), DistributedLockPollInterval = TimeSpan.FromSeconds(15.0), DeadlockRetryInterval = TimeSpan.FromSeconds(1.0), DbmsTimeSyncInterval = TimeSpan.FromMinutes(5.0), TablePrefix = "HANGFIRE_", }); serviceCollection.AddHangfire(cfg => cfg.UseStorage(storage)); serviceCollection.AddHangfireServer(); }
2. Program.cs
... builder.Services.RegisterHangfire(customSettings); var app = builder.Build(); app.UseHangfireDashboard(); ...
我尝试修改UpdateSchema属性:设为true时,表会被创建,但每次运行应用都会抛出上述错误,仿佛要重复重建索引;设为false时应用运行正常。请问我需要通过判断表是否已创建来动态切换该属性,还是我的配置本身存在错误?
环境信息
- OracleDB版本:19.17.0.0
- .NET版本:7
- NuGet包版本:Hangfire 1.8.5、Hangfire.Core 1.8.5、Hangfire.FluentNHibernateStorage 1.7.30、Hangfire.Oracle.Core 1.2.17、FluentNHibernate 3.3.0
解决方案建议
1. 排查包冲突问题
你同时引用了Hangfire.FluentNHibernateStorage和Hangfire.Oracle.Core,这两个都是Hangfire针对Oracle的存储实现,二者的Schema生成逻辑可能发生冲突,导致重复创建索引。建议只保留其中一个:如果选择FluentNHibernate作为存储层,就移除Hangfire.Oracle.Core包,避免重复的Schema操作。
2. 处理Schema更新逻辑缺陷
UpdateSchema = true时,FluentNHibernateStorage针对Oracle的Schema生成逻辑可能没有正确判断索引是否已存在,导致尝试创建重复的列组合索引。可以按以下方式处理:
- 首次部署应用时设置
UpdateSchema = true,待表和索引全部创建完成后,后续部署将该属性改为false; - 自定义Schema生成逻辑,在创建索引前先查询Oracle的
USER_INDEXES和USER_IND_COLUMNS视图,判断目标索引是否已存在,避免重复执行创建操作。
3. 动态设置UpdateSchema属性(可选)
如果不想手动修改配置,可以在启动时先检查Hangfire前缀的表是否存在,动态设置UpdateSchema的值。示例代码如下:
// 检查Hangfire表是否存在的方法 private static bool AreHangfireTablesExist(string connectionString) { using var conn = new OracleConnection(connectionString); conn.Open(); using var cmd = conn.CreateCommand(); cmd.CommandText = "SELECT COUNT(*) FROM USER_TABLES WHERE TABLE_NAME LIKE 'HANGFIRE_%'"; var count = Convert.ToInt32(cmd.ExecuteScalar()); return count > 0; } // 在配置Hangfire时使用 var tablesExist = AreHangfireTablesExist(DATABASE_URL); var storage = FluentNHibernateStorageFactory.For( ProviderTypeEnum.OracleClient10Managed, DATABASE_URL, new FluentNHibernateStorageOptions { // 保留其他原有配置 UpdateSchema = !tablesExist, TablePrefix = "HANGFIRE_", });
内容的提问来源于stack exchange,提问作者PepeTheCoder
相关产品推荐
相关产品推荐

