如何在 EF Core 中实现 Select For Update

2023-11-26

据我所知,EF(和 EF Core)中没有选项可以显式锁定我正在查询的资源,但我经常需要此功能,并且不想再重新编写每次需要时选择语句。

因为我只需要它用于 postgres 和根据规格 FOR UPDATE是查询中的最后一项,我想到的最简单的实现方法是获取如下所述的 select 语句:在 Linq to Entities 中,您可以将 IQueryable 转换为 SQL 字符串吗?并附加FOR UPDATE并直接执行。然而,这要么给我一个带有参数占位符的查询,要么不是一个准备好的查询,这意味着执行计划的缓存在 postgres 上不起作用,所以无论哪种方式都是不行的。

Linq to SQL 有方法DataContext.GetCommand但 EF 中似乎没有任何等效的东西,特别是 EF Core。我还查看了 EntityFramework.Extended 及其批量更新/删除,但由于他们必须将 select 语句转换为不同的语句,因此他们需要处理比我复杂得多的问题,因此我希望有一个更简单的解决方案。

Update:

如果描述不清楚,我想创建一个像这样的扩展方法:

public static IList<T> ForUpdate (this IQueryable<T> me)
{
    // this line is obviously what is missing for me :)
    var theUnderlyingCommand = me.GetTheUnderlyingDbCommandOrSimilar();

    theUnderlyingCommand.Text += "FOR UPDATE";
    return me.ToList();
}

这样,其他开发人员就可以像所有其他过程一样通过 Linq 使用 EF,而不是运行.ToList()他们会跑.ForUpdate()。 (对于Update故意执行查询是为了让实现更容易,也因为FOR UPDATE是 postgres 支持的最后一个选项,之后就不应该再有任何其他选项了)


这对我使用 SQL Server 有效(没有测试过的异步方法):

首先,创建一个DbCommandInterceptor(我称之为HintInterceptor.cs)

using System;
using System.Data.Common;
using System.Data.Entity.Infrastructure.Interception;
using System.Text.RegularExpressions;

public class HintInterceptor : DbCommandInterceptor
{
    private static readonly Regex _tableAliasRegex = new Regex(@"(?<tableAlias>FROM +(\[.*\]\.)?(\[.*\]) AS (\[.*\])(?! WITH \(\*HINT\*\)))", RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.Compiled);

    [ThreadStatic]
    public static string HintValue;

    private static string Replace(string input)
    {
        if (!String.IsNullOrWhiteSpace(HintValue))
        {
            if (!_tableAliasRegex.IsMatch(input))
            {
                throw new InvalidProgramException("Não foi possível identificar uma tabela para ser marcada para atualização(forupdate)!", new Exception(input));
            }
            input = _tableAliasRegex.Replace(input, "${tableAlias} WITH (*HINT*)");
            input = input.Replace("*HINT*", HintValue);
        }
        HintValue = String.Empty;
        return input;
    }

    public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
        command.CommandText = Replace(command.CommandText);
    }

    public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        command.CommandText = Replace(command.CommandText);
    }
}

所以在 Web.config 中注册你的拦截器类

<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
  <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
<interceptors> 
  <interceptor type="Full.Path.Of.Class.HintInterceptor, Dll.Name" />
</interceptors>
</entityFramework>

现在我创建一个名为 HintExtension 的静态类

public static class HintExtension
{
    public static IQueryable<T> WithHint<T>(this IQueryable<T> set, string hint) where T : class
    {
        HintInterceptor.HintValue = hint;
        return set;
    }
    public static IQueryable<T> ForUpdate<T>(this IQueryable<T> set) where T : class
    {
        return set.WithHint("UPDLOCK");
    }
}

就这样,我可以在数据库事务中使用,例如:

using(var trans = context.Database.BeginTransaction())
{
        var query = context.mydbset.Where(a => a.name == "asd").ForUpdate();
        // not locked yet
        var mylist = query.ToList();
        // now are locked for update
        // update the props, call saveChanges() and finally call commit ( or rollback)
        trans.Commit();
        // now are unlocked
}

抱歉我的英语不好,希望我的例子能有所帮助。

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

如何在 EF Core 中实现 Select For Update 的相关文章

随机推荐

  • 在 ios 7(swift) 上使用dispatch_get_global_queue时会发生EXC_BAD_INSTRUCTION

    let downloadGroup dispatch group create var images UIImage var errors NSError dispatch apply UInt urls count dispatch ge
  • Google Proximity Beacon API:如何注册 iBeacon?

    Google 的 Proximity Beacon API 文档到处都使用 Eddystone 作为示例 https developers google com beacons proximity register 然而 文档提到了另外两种
  • Jmeter - 加权随机值?

    我如何根据随机权重运行测试 控制器 例如 有两个测试 一个权重为 25 另一个权重为 50 50 的运行频率应是其两倍 也许吞吐量控制器以某种方式与随机混合 我认为您可以使用如下配置的吞吐量控制器 吞吐量值是预先设置的 可以从配置属性中设置
  • 强制一个线程阻止所有其他线程执行

    UPDATE 这个答案指出截至 2013 年 4 月 我想要做的事情是不可能的 然而 这似乎与 Alex Martelli 在Python 食谱 第 624 页 第三版 返回后 PyGILState Ensure 始终保证调用 线程具有对P
  • 如何创建切换按钮?

    我想使用 css 在 html 中创建一个切换按钮 我想要这样 当您单击它时 它会保持推入状态 而当您再次单击它时 它会弹出 如果没有办法 只能使用 css 有没有办法使用 jQuery 来做到这一点 好的语义方法是使用复选框 然后如果选中
  • 如何在 GeckoFX 中设置用户代理?

    在使用 webbrowser 控件一段时间后 我决定尝试一下 gecko 因为我遇到过 webbrowser 的问题 速度慢且性能下降 我下载了最新版本的 geckofx 16 0 0 2 和 xulrunner 16 0 2 并创建了一个
  • 在 iPhone 上从 PNG 图像读取像素颜色值的简单方法?

    有没有一种简单的方法来获取表示图像像素数据的二维数组或类似的东西 我有黑白 PNG 图像 我只想读取某个坐标处的颜色值 例如 颜色值为 20 100 This Category on UIImage might be helpful Sou
  • valgrind 可以在不退出分析应用程序的情况下输出部分报告吗?

    我想使用 valgrind 检查长时间运行的进程是否存在内存泄漏 我怀疑我所追求的内存泄漏可能仅在执行几个小时后才会发生 我可以在 valgrind 下运行应用程序并获取 valgrind 日志 但这样做意味着我必须退出应用程序并重新启动它
  • 无法应用插件“com.google.gms.google-services”

    这是我的项目构建 gradle buildscript dependencies classpath com google gms google services 3 1 0 在模块之一中构建 gradle我有这个 apply plugin
  • 从 WebHttpBinding 访问 WCF 服务中的 Session

    我正在使用 WCF 服务 通过 WebGet 属性 我正在尝试从 WCF 服务访问 Session 但 HttpContext Current 为 null 我添加了 AspNetCompatibilityRequirements 并编辑了
  • 在摩纳哥编辑器的上下文菜单中禁用剪切和复制

    我正在使用摩纳哥编辑器 我看到在以后的版本中 上下文菜单中添加了剪切和复制功能 我想从上下文菜单中删除这两个选项 请让我知道我怎样才能实现它 完整代码 import as actions from monaco editor esm vs
  • jQuery 脚本仅在 ie8/9 开发者工具下工作

    我正在尝试调试无法在 IE 上运行的 jQuery Tools 脚本 可以在这里找到一个例子 http dl dropbox com u 16799097 www demo jQuery Slider index html 它正确加载 第一
  • Xcode 8 中的“Vary for Traits”是什么?

    我正在使用 AutoLayout 和 Size 类 但随着 iOS 10 和新 Xcode 8 0 的发布 出现了一个新选项Vary for Traits 这是针对不同宽度和高度的设备的 Size Class 的替换吗 通过选择width复
  • HTML5 会话存储发送到服务器

    如果我是对的 会话存储存储在客户端 并且只能通过一个选项卡访问 如何将会话存储中存储的信息发送到服务器 我可以使用 cookie 但如果我打开 2 个选项卡 cookie 将被第二个选项卡重写 Thanks 存储对象 localStorag
  • Java:在特定代码块上设置超时?

    是否有可能在某些代码块运行时间超过可接受的时间后强制 Java 抛出异常 这是我所知道的最简单的方法 final Runnable stuffToDo new Thread Override public void run Do stuff
  • grep 带有特殊字符

    我想在以下向量中找到包含星号字符的元素 s lt c A B C D E grep s 1 1 2 3 4 5 这是行不通的 我能理解 因为这是一个特殊的角色 当我阅读时here 我决定在星号之前使用 但这给了我一个错误 grep s Er
  • 我应该将 setup.py 生成的 MANIFEST 文件保留在版本控制下吗?

    当我维护和分发 Python 包时 我应该保留该命令的 MANIFEST 文件吗 python setup py sdist 在版本控制下生成 还是应该将其添加到 gitignore 该文件是根据一些关于源代码分发中包含哪些文件的常用想法生
  • 用于测量代码行数的 Eclipse 插件

    我正在运行 Eclipse Helios 3 6 想知道是否有一个不错的插件可以计算logicaljava 源文件中的代码行 从逻辑上讲 我的意思是 if j gt 6 j 换句话说 将计算 2 行逻辑代码 2 条语句 而不是 3 行物理代
  • Jetpack Compose Navigation 的导航设计是否良好?

    以下代码来自官方示例project 有两个分行 main and end 我找到了代码主要和Code end使用不同的方式进行导航 代码主要简单明了 在其他项目中 它基于状态进行导航 就像代码 A 一样 来自project Code end
  • 如何在 EF Core 中实现 Select For Update

    据我所知 EF 和 EF Core 中没有选项可以显式锁定我正在查询的资源 但我经常需要此功能 并且不想再重新编写每次需要时选择语句 因为我只需要它用于 postgres 和根据规格 FOR UPDATE是查询中的最后一项 我想到的最简单的