二开案例.服务插件.高并发下控制单据编号重复问题

【应用场景】
业务单据通常会在保存操作上配置编码唯一校验器,用于控制单据编号重复的问题,但是在WebApi高并发下,由于校验器的机制问题,使得校验结果具有一定的滞后性,因此仍有可能会产生重复单号的单据。此时,依赖数据库的唯一索引控制单据编号重复,是最高效,最佳的选择。
【案例演示】
采购订单,通过在数据库新建单据编号表,并给单据编号字段设置为主键,依托数据库的主键的数据唯一性检查,进行高并发下的单据编号重复控制。

【实现步骤】
<1>编写服务插件,代码如下。
using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.Metadata.FieldElement;
using Kingdee.BOS.Core.Metadata.FormElement;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.Util;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Transactions;
namespace Jac.XkDemo.BOS.App.PlugIn
{
/// <summary>
/// 【服务插件】高并发下控制单据编号重复问题(保存)
/// </summary>
[Description("【服务插件】高并发下控制单据编号重复问题(保存)"), HotUpdate]
public class BillNoUniqueSaveServicePlugIn : AbstractOperationServicePlugIn
{
public override void EndOperationTransaction(EndOperationTransactionArgs e)
{
base.EndOperationTransaction(e);
var billNoField = this.BusinessInfo.GetBillNoField() as BillNoField;
if (billNoField == null)
{
return;
}
var formId = this.BusinessInfo.GetForm().Id;
#region 先删
string ids;
if (this.BusinessInfo.GetForm().PkFieldType == EnumPkFieldType.STRING)
{
ids = string.Join(",", e.DataEntitys.Select(o => "'" + Convert.ToString(o[0]) + "'").ToArray());
}
else
{
ids = string.Join(",", e.DataEntitys.Select(o => Convert.ToString(o[0])).ToArray());
}
var sqlGetOldBillNo = string.Format("SELECT {2},{0} FROM {1} WHERE {2} IN ({3})", billNoField.FieldName, this.BusinessInfo.GetEntity(0).TableName, this.BusinessInfo.GetForm().PkFieldName, ids);
DynamicObjectCollection oldBillNoObjs;
using (var trans = new KDTransactionScope(TransactionScopeOption.Suppress))
{
oldBillNoObjs = DBUtils.ExecuteDynamicObject(Context, sqlGetOldBillNo);
}
if (oldBillNoObjs != null && oldBillNoObjs.Count > 0)
{
var dicOld = new Dictionary<string, string>();
foreach (var obj in oldBillNoObjs)
{
var billNo = Convert.ToString(obj[1]);
if (string.IsNullOrWhiteSpace(billNo))
{
continue;
}
dicOld[Convert.ToString(obj[0])] = Convert.ToString(obj[1]);
}
var needDeleteBillNos = new List<string>();
foreach (var dataEntity in e.DataEntitys)
{
var id = Convert.ToString(dataEntity[0]);
var billNo = Convert.ToString(dataEntity[billNoField.PropertyName]);
if (dicOld.ContainsKey(id) && dicOld[id] != billNo)
{
// 单号被修改,旧单号删除
needDeleteBillNos.Add(dicOld[id]);
}
}
if (needDeleteBillNos.Count > 0)
{
var sqlDeleteOldBillNo = string.Format("DELETE FROM T_JAC_BILLNO_UNIQUECHECK WHERE FOBJECTID='{0}' AND FBILLNO IN ({1})", formId, string.Join(",", needDeleteBillNos.Select(o => "'" + o + "'")));
DBUtils.Execute(Context, sqlDeleteOldBillNo);
}
}
#endregion
#region 再增
var sqlTemplate = "INSERT INTO T_JAC_BILLNO_UNIQUECHECK (FOBJECTID,FBILLNO) VALUES (@FOBJECTID,@FBILLNO)";
var sqlObjs = new List<SqlObject>();
foreach (var dataEntity in e.DataEntitys)
{
var billNo = dataEntity[billNoField.PropertyName] as string;
if (!string.IsNullOrWhiteSpace(billNo))
{
var sqlObj = new SqlObject(sqlTemplate, new SqlParam("@FOBJECTID", KDDbType.AnsiString, formId));
sqlObj.Param.Add(new SqlParam("@FBILLNO", KDDbType.String, billNo));
二开案例.服务插件.高并发下控制单据编号重复问题
【应用场景】业务单据通常会在保存操作上配置编码唯一校验器,用于控制单据编号重复的问题,但是在WebApi高并发下,由于校验器的机制问题,...
点击下载文档文档为doc格式
声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。
上一篇
已经是第一篇



