如果临时表发生错误,使 EF Core 更具弹性

问题描述 投票:0回答:1

在 Ef Core 上调用 SaveChangesAsync 时出现以下错误 - 错误 0x80131904

Data modification failed on system-versioned table 'table name' because transaction 
time was earlier at than period start time for affected records.

我知道此错误与历史表中的有效起始日期和有效截止日期有关,如果发生大量活动,则会导致重叠

我知道这个错误是设计使然,我无法真正避免它

但是,我需要一个解决方案,以便在发生异常时重试 SaveChangesAsync 调用,并显示此消息

我认为解决方案是在数据库初始化时

options.UseSqlServer(connectionString,
    sqlOptions =>
    {
        sqlOptions.MigrationsAssembly(MigrationAssemblyName);
        sqlOptions.EnableRetryOnFailure(maxRetryCount: 10,
            TimeSpan.FromSeconds(30),
            new List<int>()
            {
                80131904
            });
            sqlOptions.CommandTimeout(240);
    });

参数

new List<int>()
{
  80131904
};

但是,我不确定这是否正确,或者在这种情况下是否有更好的重试方法?

这个数字正确吗?它似乎是十六进制,但将其转换为数字会得到一个比 int 可以容纳的数字更大的数字

这个错误号似乎与错误消息没有具体关系,感觉这已经是一个被归类为瞬态的错误号?

错误号似乎是十六进制,但是当转换为十六进制时,它太大而无法存储为整数

有人有这方面的经验吗?

保罗

c# entity-framework entity-framework-core
1个回答
0
投票

不,这不太正确。 SQL 错误号是

13535
而不是
80131904
(这只是
SqlException
的 HResult 的十六进制)。您可以在
exception.Number
属性中看到错误号。

options.UseSqlServer(connectionString,
    sqlOptions =>
    {
        sqlOptions.MigrationsAssembly(MigrationAssemblyName);
        sqlOptions.EnableRetryOnFailure(
            maxRetryCount: 10,
            TimeSpan.FromSeconds(30),
            new []{ 13535 }
        );
        sqlOptions.CommandTimeout(240);
    });

唯一的其他选择是使用某种锁定机制。例如,您可以在同一事务中添加显式命令

SELECT TOP (1) 1 AS dummy
FROM Table WITH (UPDLOCK, TABLOCK);

这将防止任何修改,同时仍然允许

SELECT
查询。

或者,您可以使用

sp_getapplock
来控制对修改过程的访问:同样,这将阻止任何其他人尝试获得相同的锁,但允许任何不这样做的人。


请注意,此错误可能与其他交易无关。如果您对

DEFAULT
列的
PERIOD
约束不够精确,那么您可能会在自己的行上出现舍入错误。确保始终使用
SYSUTCDATETIME()
来防止出现问题。

© www.soinside.com 2019 - 2024. All rights reserved.