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

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

内容简介: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数据库。


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

查看所有标签

猜你喜欢:

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

软件随想录

软件随想录

Joel Spolsky / 阮一峰 / 人民邮电出版社 / 2009 / 49.00元

《软件随想录:程序员部落酋长Joel谈软件》是一部关于软件技术、人才、创业和企业管理的随想文集,作者以诙谐幽默的笔触将自己在软件行业的亲身感悟娓娓道来,观点新颖独特,内容简洁实用。全书分为 36讲,每一讲都是一个独立的专题。 《软件随想录:程序员部落酋长Joel谈软件》从不同侧面满足了软件开发人员、设计人员、管理人员及从事软件相关工作的人员的学习与工作需要。一起来看看 《软件随想录》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

随机密码生成器
随机密码生成器

多种字符组合密码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具