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


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

查看所有标签

猜你喜欢:

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

JavaScript DOM高级程序设计

JavaScript DOM高级程序设计

Jeffrey Sambells、Aaron Gustafson / 李松峰、李雅雯 / 人民邮电出版社 / 2008-7 / 59.00元

本书注重理论与实践的结合,全面讲述高级的DOM 脚本编程。全书分为3 个部分:第一部分“深入理解DOM 脚本编程”,涉及W3C DOM 规范的各方面,包括非标准的浏览器支持和不支持的内容;第二部分“浏览器外部通信”,以Ajax 和客户端—服务器端通信为主题;第三部分“部分高级脚本编程资源”,集中介绍了一批第三方脚本编程资源,包括库和API。同时,每部分的最后一章都为案例研究,将学到的内容应用于实践......一起来看看 《JavaScript DOM高级程序设计》 这本书的介绍吧!

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

多种字符组合密码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具