专栏首页程序员的SOD蜜在OQL上使用UPDLOCK锁定查询结果,安全的更新实体数据

在OQL上使用UPDLOCK锁定查询结果,安全的更新实体数据

SqlServer查询记录的时候提供多种锁定方式,其中UPDLOCK 的优点是允许您读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。当我们用UPDLOCK来读取记录时可以对取到的记录加上更新锁,从而加上锁的记录在其它的线程中是不能更改的只能等本线程的事务结束后才能更改。 有时候我需要控制某条记录在我读取后就不许再进行更新,那么我就可以将所有要处理当前记录的查询都加上更新锁,以防止查询后被其它事务修改.将事务的影响降低到最小。假如不这样做,将整个表锁定,这种做法将严重影响了性能。

看下面的查询:

begin tran
select * from address WITH (UPDLOCK) where [Name]='Z'
waitfor delay '00:00:10' 
update address set [Name]='X' where [Name]='Z' 
commit tran

这个示例中,在读取记录后,等待10秒来模拟耗时的操作,之后再更新这条记录。 上面这个例子可能比较抽象,让我们来举一个实际的例子。 假设有一个投资产品表,当我们查询到该产品记录后,要进行一系列的判断,最后对该记录进行更新。该记录的状态会影响到下一个人查询到此记录的处理。下面我们来看看用SOD框架的OQL怎么处理。

           decimal sumAmount = model.Amount + model.GvMoney;
            DateTime currentTime = DateTime.Now;
            AdoHelper db = AdoHelper.CreateHelper("defaultDB");
            
            db.BeginTransaction();
            try
            {
                //查询相关产品余额剩多少够不够买的
                var pro = EntityQuery<Pro_Products>.QueryObject(
                    OQL.From<Pro_Products>()
                        .With(OQL.SqlServerLock.UPDLOCK)
                        .Select()
                        .Where<Pro_Products>((cmp, p) => cmp.Property(p.proNumber) == model.ProNumber)
                        .END, db);
                if (pro == null)
                {
                    db.Rollback();
                    return new OrderingModel { Msg = "剩余可投金额不足" };
                }
                //2015 08 06 打开原有注释,限制投资金额  
                if (sumAmount < 10 || sumAmount % 10 != 0)
                {
                    db.Rollback();
                    return new OrderingModel { Msg = "投标金额不正确" };
                }

                //线下标下单时,不可使用现金券 
                if (SetObject.IsOffline(pro.ProType))
                {
                    sumAmount = model.Amount;
                }
                if (pro.Surplus < sumAmount)
                {
                    db.Rollback();
                    return new OrderingModel { Msg = "剩余可投金额不足" };
                }
                if (currentTime < pro.starttime)
                {
                    db.Rollback();
                    return new OrderingModel { Msg = "还未开始" };
                }
                var giveAward = 0;
                if (pro.Surplus == sumAmount)
                {
                    if (sumAmount >= 5000 && sumAmount < 10000)
                    {
                        giveAward = 1;
                    }
                    if (sumAmount >= 10000)
                    {
                        giveAward = 2;
                    }
                }
                //扣除产品可用金额
                pro.Surplus -= sumAmount;
                if (pro.Surplus == 0)//最后一笔 更新满标状态
                {
                    pro.Prostatus = "2";
                    //pro.Paymentime = currentTime.AddDays(1);
                    pro.Paymentime = currentTime;
                    //
                    pro.ProOrder = 0;
                }

                EntityQuery<Pro_Products>.Instance.Update(pro, db);
 
                //其它复杂的处理逻辑,更新其它表的操作,略...

                  db.Commit();

上面的操作,首先在AdoHelper对象上开启事务,然后查询投资产品实体的时候在With方法上加上 OQL.SqlServerLock.UPDLOCK 更新锁,接着进行复制的业务处理,然后更新此实体记录,之后还有复杂的其它业务操作,最后提交事务。

我们看到,OQL的这种更新锁操作,跟直接写SQL语句操作很类似,OQL执行的时候也是这样输出SQL语句的,这样确保数据记录在并发的时候,安全的更新。

注意:OQL更新锁目前只支持SqlServer数据库。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • TOP语句放到表值函数外,效率异常低下

    在XXX系统中,有一个获取客户数据的SQLSERVER 表值函数,如果使用管理员登录,这个函数会返回150W行记录,大概需要30秒左右,但如果将TOP语句放到表...

    用户1177503
  • 在SQLMAP中使用动态SQL

    最近有几个同事和朋友询问如何在SQLMAP中“拼接字符串”,因为有时候条件的数量不固定,条件参数类型也不固定,无法写出 @参数名 这样的SQL语句,也就是大家常...

    用户1177503
  • .net异步性能测试(包括ASP.NET MVC WebAPI异步方法)

    很久没有写博客了,今年做的产品公司这两天刚刚开了发布会,稍微清闲下来,想想我们做的产品还有没有性能优化空间,于是想到了.Net的异步可以优化性能,但到底能够提升...

    用户1177503
  • Python参数类型以及常见的坑

    这个输出的结果应该是意料之中,现在我们这时候再调用Book()方法,看看会发生什么:

    py3study
  • 06-性能测试之JMeter参数化

    参数化是自动化测试脚本的一种常用技巧。简单来说,参数化的一般用法就是将脚本中的某些输入使用参数来代替,在脚本运行时指定参数的取值范围和规则,这样,脚本在运行的时...

    测试邦
  • Salesforced的重复管理

    看到多个小伙伴在后台输入Duplicate,实在不忍,于是今天整理了这篇文章,供大家学习,参考。下图是我在系统里设置的一个重复规则,当客户名字和行业一致的时候则...

    臭豆腐
  • 【视频】云API组合应用实战: 英汉互译小工具

    云API团队在云学院上线了一套视频教程,目的是和大家分享如何进行API、SDK和CLI的使用。

    Dfounderliu
  • Confluence 6 配置系统属性 原

    在这个页面中描述 Confluence 启动时如何设置 Java 属性和其他选项。

    HoneyMoose
  • 这样处理shell脚本参数,爽多了!

    只要顺序一变,参数就对应不上了。假设你有时候不需要第二个参数,要使用第三个参数,你是不是还必须得输入第二个参数?

    编程珠玑
  • 回忆杀!红警95的代码开源了!我来教你怎么玩

    红色警戒系列(Command & Conquer: Red Alert)全称“命令与征服:红色警戒”,是西木工作室(WestWood)在1997年开始发行的系列...

    IT苦逼一枚

扫码关注云+社区

领取腾讯云代金券