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

栏目: 数据库 · 发布时间: 6年前

内容简介:SqlServer查询记录的时候提供多种锁定方式,其中UPDLOCK 的优点是允许您读取数据(不阻塞其它事务)并在以后更新数据,同时确保自从上次读取数据后数据没有被更改。当我们用UPDLOCK来读取记录时可以对取到的记录加上更新锁,从而加上锁的记录在其它的线程中是不能更改的只能等本线程的事务结束后才能更改。看下面的查询:这个示例中,在读取记录后,等待10秒来模拟耗时的操作,之后再更新这条记录。

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数据库。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

jQuery实战

jQuery实战

Bear Bibeault、Yehuda Katz / 陈宁 / 人民邮电出版社 / 2009.1 / 49.00元

《jQuery实战》全面介绍jQuery知识,展示如何遍历HTML文档、处理事件、执行动画以及给网页添加Ajax。书中紧紧地围绕“用实际的示例来解释每一个新概念”这一宗旨,生动描述了jQuery如何与其他工具和框架交互以及如何生成jQuery插件。jQuery 是目前最受欢迎的JavaScript/Ajax库之一,能用最少的代码实现最多的功能。 点击链接进入新版: jQuery......一起来看看 《jQuery实战》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

html转js在线工具
html转js在线工具

html转js在线工具