需要一种内置方法来为现有存储库的 Dapper 添加死锁恢复能力,而无需更改它们

2024-04-13

需要全部做完现有的回购协议(大约 30+)对死锁具有容错能力,并通过日志和等待方法从死锁中恢复。

尝试成功:经过一些研究并根据项目进行定制后,我使用 Polly 回答了下面的自定义 SqlResiliencyPolicy。

但是,我寻求的是:目前的方式(PFB 回答),要求我要么

  1. 将所有现有的数据库调用包装起来await _policy.ExecuteAsync OR
  2. 提供接受的自定义重载IAsyncPolicy参数。然后调用预期的方法。 IDbConnection 的扩展类型:

public static Task<T> GetAsync<T>(this IDbConnection connection, object primaryKey, IAsyncPolicy policy) => return await _policy.ExecuteAsync(async () => GetAsync<T> (...));

无论采用哪种方式,我都需要更改所有 30 多个存储库。但是,在 dapper/some-other-approaches 中是否有一种内置的方法,我们可以

“在启动时配置一个策略,并通过以下方式自动神奇地所有数据库调用 dapper 变得有弹性(退回到他们的容错机制) 类似于添加策略的http客户端弹性方式 当您注册客户时”

这样:将代码更改降至最低,无需触及存储库,而只需启动。

我有以下方法,需要对其进行改进。


已实施第二种方法 ^^:这将要 DI'ed 的策略与现有存储库分离。扩展方法IDbConnection负责围绕现有方法包装策略。

public class SqlResiliencePolicyFactory
{
    private readonly ISet<int> _transientDbErrors = new HashSet<int>(new[] { 1205 });
    private readonly ILogger _logger;
    private readonly IConfiguration _configuration;

    public SqlResiliencePolicyFactory(ILogger logger, IConfiguration configuration)
    {
        _logger = logger;
        _configuration = configuration;
    }

    public IPolicyRegistry<string> GetSqlResiliencePolicies(int transientErrorRetries = 3)
    {
        return new PolicyRegistry
        {
            { 
                "DbDeadLockResilience", 
                Policy
                    .Handle<SqlException>(ex => _transientDbErrors.Contains(ex.Number))
                    .WaitAndRetry(
                        retryCount: transientErrorRetries,
                        sleepDurationProvider: attempt => TimeSpan.FromMilliseconds(attempt * 100),
                        onRetry: LogRetryAction)
            },
            { 
                "DbDeadLockResilienceAsync", 
                Policy
                    .Handle<SqlException>(ex => _transientDbErrors.Contains(ex.Number))
                    .WaitAndRetryAsync(
                        retryCount: transientErrorRetries,
                        sleepDurationProvider: attempt => TimeSpan.FromMilliseconds(attempt * 100),
                        onRetry: LogRetryAction)
            }
        };
    }
    
    private void LogRetryAction(Exception exception, TimeSpan sleepTime, int reattemptCount, Context context) =>
        _logger.Log(
            LogLevel.Warning,
            exception,
            @$"Transient DB Failure while executing query,
                error number: {((SqlException)exception).Number};
                reattempt number: {reattemptCount}");
}

启动时:

DapperExtensions.SetPolicies(new SqlResiliencePolicyFactory(_logger, _configuration)
                            .GetSqlResiliencePolicies());

在单独的类中创建扩展方法,以将策略包装到存储库的现有方法中。 扩展方法:

public static class DapperExtensions
{
    private static Policy _policy = Policy.NoOp();
    private static IAsyncPolicy _asyncPolicy = Policy.NoOpAsync();

    public static void SetPolicies(IReadOnlyPolicyRegistry<string> readOnlyPolicyRegistry)
        {
            _policy = readOnlyPolicyRegistry.Get<Policy>("DbDeadLockResilience");
            _asyncPolicy = readOnlyPolicyRegistry.Get<IAsyncPolicy>("DbDeadLockResilienceAsync");
        }

    public static T GetFirstWithRetry<T>(this IDbConnection connection,
                                        string? sql = null, object? parameters = null, IDbTransaction? transaction = null) where T : class =>
        _policy.Execute(() => connection.GetFirst<T>(sql, parameters, transaction));

    public static T QueryFirstOrDefaultWithRetry<T>(this IDbConnection connection, string sql,
                                          object? parameters = null, IDbTransaction? transaction = null) =>
        _policy.Execute(() => connection.QueryFirstOrDefault<T>(sql, parameters, transaction));

    public static async Task<bool> UpdateAsyncWithRetry<T>(this IDbConnection connection, T entityToUpdate, IEnumerable<string> columnsToUpdate,
                                                      IDbTransaction? transaction = null) where T : class =>
        await _asyncPolicy.ExecuteAsync(async () => await connection.UpdateAsync(entityToUpdate, columnsToUpdate, transaction));

    //Similarly, add overloads to all the other methods in existing repo.
}

Now,

  1. 现有的回购协议独立于政策(没有 DI 到回购协议)。
  2. 政策按照 SRP 保存在单独的位置。
  3. Dapper 扩展可以更改策略以便于测试。

因此,现有的存储库必须更改名称并调用上面的包装器,而不是调用 dapper 方法本身,才会应用策略。不要忘记对存储库进行一次回归测试。

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

需要一种内置方法来为现有存储库的 Dapper 添加死锁恢复能力,而无需更改它们 的相关文章

  • 为什么使用abs()或fabs()而不是条件否定?

    在 C C 中 为什么要使用abs or fabs 不使用以下代码即可查找变量的绝对值 int absoluteValue value lt 0 value value 这与较低级别的指令较少有关吗 您提出的 有条件的abs 并不等于std
  • 赋值运算符和复制构造函数有什么区别?

    我不明白C 中赋值构造函数和复制构造函数之间的区别 是这样的 class A public A cout lt lt A A lt lt endl The copy constructor A a b The assignment cons
  • 在 C++ 中分割大文件

    我正在尝试编写一个程序 该程序接受一个大文件 任何类型 并将其分成许多较小的 块 我想我已经有了基本的想法 但由于某种原因我无法创建超过 12 kb 的块大小 我知道谷歌等上有一些解决方案 但我更感兴趣的是了解这个限制的根源是什么 然后实际
  • 如何进行带有偏差的浮点舍入(始终向上或向下舍入)?

    我想以偏置舍入浮动 要么总是向下 要么总是向上 代码中有一个特定的点 我需要这个 程序的其余部分应该像往常一样四舍五入到最接近的值 例如 我想四舍五入到最接近的 1 10 倍数 最接近 7 10 的浮点数约为 0 69999998807 但
  • 获取两个字符串之间的公共部分c# [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要的是获取两个单词之间的共同部分并获取差异 例子 场景1 word1 感言 word2 Test 将返回 公共部分Test 不同之
  • 当我单击 C# 中的“取消”按钮时重定向到新页面(Web 部分)

    Cancel button tc new TableCell btnCancel new Button btnCancel Text Cancel btnCancel Click new EventHandler btnCanel Clic
  • 捕获 foreach 条件中抛出的异常

    我有一个foreach在 foreach 本身的条件下循环期间中断的循环 有没有办法try catch抛出异常然后继续循环的项 这将运行几次 直到异常发生然后结束 try foreach b in bees exception is in
  • 有什么工具可以说明每种方法运行需要多长时间?

    我的程序的某些部分速度很慢 我想知道是否有我可以使用的工具 例如它可以告诉我可以运行 methodA 花了 100ms 等等 或者类似的有用信息 如果您使用的是 Visual Studio Team System 性能工具 中有一个内置分析
  • std::map 和二叉搜索树

    我读过 std map 是使用二叉搜索树数据结构实现的 BST 是一种顺序数据结构 类似于数组中的元素 它将元素存储在 BST 节点中并按其顺序维护元素 例如如果元素小于节点 则将其存储在节点的左侧 如果元素大于节点 则将其存储在节点的右侧
  • TextBox 焦点的 WinForms 事件?

    我想添加一个偶数TextBox当它有焦点时 我知道我可以用一个简单的方法来做到这一点textbox1 Focus并检查布尔值 但我不想那样做 我想这样做 this tGID Focus new System EventHandler thi
  • 为什么密码错误会导致“填充无效且无法删除”?

    我需要一些简单的字符串加密 所以我编写了以下代码 有很多 灵感 来自here http www codeproject com KB security DotNetCrypto aspx create and initialize a cr
  • C++11 函数局部静态 const 对象的线程安全初始化

    这个问题已在 C 98 上下文中提出 并在该上下文中得到回答 但没有明确说明有关 C 11 的内容 const some type create const thingy lock my lock some mutex static con
  • 如何用 kevent() 替换 select() 以获得更高的性能?

    来自Kqueue 维基百科页面 http en wikipedia org wiki Kqueue Kqueue 在内核和用户空间之间提供高效的输入和输出事件管道 因此 可以修改事件过滤器以及接收待处理事件 同时每次主事件循环迭代仅使用对
  • 两组点之间的最佳匹配

    I ve got two lists of points let s call them L1 P1 x1 y1 Pn xn yn and L2 P 1 x 1 y 1 P n x n y n 我的任务是找到它们点之间的最佳匹配 以最小化它
  • UWP 无法在两个应用程序之间创建本地主机连接

    我正在尝试在两个 UWP 应用程序之间设置 TCP 连接 当服务器和客户端在同一个应用程序中运行时 它可以正常工作 但是 当我将服务器部分移动到一个应用程序并将客户端部分移动到另一个应用程序时 ConnectAsync 会引发异常 服务器未
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 内核开发和 C++ [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 从我know https stackoverflow com questions 580292 what languages are windo
  • 如何查明CONFIG_FANOTIFY_ACCESS_PERMISSIONS是否启用?

    我想利用fanotify 7 http man7 org linux man pages man7 fanotify 7 html我遇到的问题是在某些内核上CONFIG FANOTIFY ACCESS PERMISSIONS不起作用 虽然C
  • 如何确定母版页中正在显示哪个子页?

    我正在母版页上编写代码 我需要知道正在显示哪个子 内容 页面 我怎样才能以编程方式做到这一点 我用这个 string pageName this ContentPlaceHolder1 Page GetType FullName 它以 AS

随机推荐

  • 计算所有 1 和 0 相等的二进制数

    我正在实现等边双分区算法的二进制表示 我想知道迭代具有相等 N 2 1 和 0 的 N 位的所有组合的最佳方法是什么 我试图找到最快的方法 而不是最简单的编码方法 谢谢 只是 N choose N 2 你要选择哪些位是 0 其余的是 1 如
  • 在法国 Windows Server 上使用 django 换行的问题

    Problem 当将通过 render to string 读入的字符串写入文件时 我的 Django 应用程序在每个 CRLF 之前引入一个 CR 在我的模板文件中 我使用了 CRLF Django 处理应用程序编写了一个文件 在每个 C
  • 自动加载和命名空间

    我使用 PHP 已经很长时间了 但现在开始尝试新的语言功能 例如命名空间 我有一个关于自动加载的问题 但在网络搜索中找不到足够的答案 假设我在不同的命名空间中有类 namespace foo bar baz class Quux names
  • 将java代码编译为exe(例如使用Launch4Java)是否确保代码无法被逆向工程?

    经过我自己的实验 我确信 Java 代码混淆在防止逆向代码工程方面并不安全 因此 我转而使用 Launch4J 将我的核心 jar 文件之一捆绑到单个 EXE 文件中 jar 文件还包含主要的入口方法 这会再次保护代码逆向工程吗 如果计算机
  • ASP/VBScript - Int() 与 CInt()

    ASP VBScript 之间有什么区别Int and CInt Int http www w3schools com Vbscript func int asp Int 函数返回指定数字的整数部分 CInt http www w3scho
  • 分组data.fame后的自定义函数

    给定以下数据框 d lt rep c a b each 5 l lt rep 1 5 2 v lt 1 10 df lt data frame d d l l v v v df d l v 1 a 1 1 2 a 2 4 3 a 3 9 4
  • 如何处理复杂的事情?

    您知道代码中对于项目至关重要但可能需要花费大量时间才能完成的特定部分吗 您是否有过这样的感觉 您宁愿做其他事情 可能不太重要 或者根本不写代码 而不是做那部分 你竭尽全力避免并使用你所知道的每一个懒惰技巧来推迟其不可避免的实施的那头野兽 现
  • 我可以对任意排列的浮点数向量进行确定性求和吗?

    假设我有一个 可能很大 由某些黑盒过程产生的浮点数向量 是否可以计算这些数字的按位可再现总和 如果黑盒过程总是以相同的顺序产生数字 那么按位可再现的求和很容易 只需从左到右对它们求和即可 但是 如果数字以随机顺序生成 也许是因为它们是从异步
  • 正则表达式匹配字符串之间的数字

    我需要从字符串 start 和 end 之间的以下文本中提取整数值 并且only之间 111222 garbage 999888 start 123456 end start 654321 end 想要的结果 123456 654321 这
  • 导致TTS初始化失败的原因有哪些?

    在以下场景中观察到 TTS 初始化错误 该错误过于随机 TTS 引擎已安装 语音集已存在 并且可以从辅助功能选项中播放示例 tts TTS 初始化在先前初始化和播放的同一设备上随机失败 在不同的设备 一加 华硕 三星 和各种 Android
  • UICollectionView - 滚动到下一页

    是否有机会使用 UICollectionView 滚动到所需的项目 scrollToItemAtIndexPath 并且不捕捉到项目本身 而是捕捉到项目所属的页面 我启用了分页功能 Cheers 你需要创建NSIndexPath而不是滚动到
  • 创建自定义 UTI 以与空投、iOS 一起使用

    我在 info plist 中使用此代码
  • 在 Bash 中动态构建命令管道

    我正在编写一个带有选项的 bash 程序 例如 my program l 3 a s l 3将输出限制为三行 a将选择我的所有文件 s将对输出进行排序 现在 我可以这样一次使用两个选项 if all 1 then if sort 1 the
  • 升级 ng-jhipster 库以兼容 Angular 16.2.0

    我正在开发一个依赖 ng jhipster 库的 Angular 应用程序 特别是版本 0 16 0 以下是 ng jhipster 的 package json 中的相关部分 name ng jhipster description A
  • 由于“无法获取 QuerySet 类的 repr”错误,嵌套序列化器上的非空约束失败

    尝试在我的 DRF 项目中使用基本的消息传递功能 我似乎对嵌套序列化器验证有问题 我是 DRF 的新手 已经阅读文档几天了 但我一定错过了一些东西 错误发生在行内message Message objects create validate
  • JIT 与解释器

    我找不到 JIT 和解释器之间的区别 Jit 是解释器和编译器的中介 在运行时 它将字节代码转换为机器代码 JVM 或实际机器 下次 它从缓存中获取并运行 我对吗 解释器将直接执行字节码 而不将其转换为机器代码 是对的吗 我们电脑中真正的处
  • HTML5 视频 JavaScript 控件 - 重新启动视频

    我知道如何使用 play 和pause 开始和停止视频 但是如何使用 javascript 将视频放回到 HTML5 的开头 有没有办法将指针移回开头 Set the currentTime http www w3 org TR html5
  • 针对特定集合的多对多关系核心数据查询

    public enum Ability String case newcomer Newcomer case beginner Beginner case intermediate Intermediate case advanced Ad
  • ActiveRecord 包括。指定包含的列

    我有模特个人资料 个人资料有 一个用户 用户模型具有字段电子邮件 当我打电话时 Profile some scope includes user it calls SELECT users FROM users WHERE users id
  • 需要一种内置方法来为现有存储库的 Dapper 添加死锁恢复能力,而无需更改它们

    需要全部做完现有的回购协议 大约 30 对死锁具有容错能力 并通过日志和等待方法从死锁中恢复 尝试成功 经过一些研究并根据项目进行定制后 我使用 Polly 回答了下面的自定义 SqlResiliencyPolicy 但是 我寻求的是 目前