每一個企業應用中不可避免的都會涉及到業務編碼規則的問題,比如訂單管理系統中的訂單編號,比如商品管理系統中的商品編碼,比如項目管理系統中的項目編碼等等,這一系列的編碼都需要管理起來,那麼它們的應該如何編碼的,具體的編碼規則我們很多時候都是直接寫在程序當中
常用的的編碼有:
1、數據庫自增長ID或最大值加1
2、GUID
3、時間戳
4、常量+自增長
5、常量+時間戳+自增長
6、根據單據屬性編碼 比如商品編碼:第X是代碼商品顏色,第Y位是代碼商品產地
7、自定義函數處理返回
8、其它
添加一張單據時,這個單據的編碼是比較頭疼
第一個問題就是單據編碼的時間順序:
1、新增前先預取得新單據編碼
優點是保存處理很簡單,而且保存後不需要再刷新UI,缺點就是如果放棄表單那麼編碼計數已經跳號,做不到連續的單據號,而且沒法實現上面編碼的第6種情況。
2、保存時才生成單據編碼
缺點是保存比較麻煩點,而且保存後需要再刷新UI中的單據編碼字段,但是如果是需要根據單據屬性編碼,那就必做得使用這種方式了,而且能做到單據連續。
第二個問題是這個編碼該怎麼去取,怎麼保證唯一性
這裡要看是使用哪種編碼方式,比如 max + 1 這種方式 就直接檢索數據庫 select max(id) + 1 from table 取得編碼,如果是GUID則比較方便,但是GUID看著實在是有點惡心,使用時間戳的話如果精確到秒的話是沒辦法保證唯一性的,即使精確到毫秒理論上也是不行的。其它復雜的編碼獲取就更麻煩點了。總之不是很方便就能取得。
第三個問題如果這個編碼規則需要更換怎麼辦
這個如果沒有特別設計編碼規則一般都要修改程序,沒辦法說不動程序直接修改配置就能實現
Ⅰ、鑒於以上幾個問題,我們想設計一個比較通用的業務編碼規則模塊,以後的項目也可復用,它應該要實現以下功能及特點:
1、滿足各種編碼規則的需求
a.背景中提到的那7種都要實現,還要求各種規則可以自由組合
b.依賴重置,比如日期變化時序號自動重置為1
b.支持SAAS模式的業務需求
2、拓展性強,可添加自定義規則
3、通過配置文件或數據進行配置,修改業務編碼規則只需要修改配置文件或數據
4、使用簡單
Ⅱ、我們先從配置來設計,我們把規則配置放在數據庫中,可以考慮以後再做個界面來管理這些配置。設計三張表來保存這些規則
1、單據編碼規則
2、租戶單據編碼規則 (考慮SAAS多租戶模式)
3、單據編碼規則 用來存儲基礎規則組合,一種單據編碼對應多種規則
通過以上使用,我們大致清楚,Sequence對象中主要就是一個Next()的實現,創建交給SequenceFactory以下是我的一個實現截圖
DefaultSequenceFactory.cs
ISequence Create( new Sequence(name);
ISequence.cs
<, > name, Next(
Sequence.cs
Sequence(= === ISequence SetTenantID(= ISequence SetValues(Dictionary<, >= (row != (JProperty item (item != ) _context.row[item.Name] = ISequence SetValue( name, (!= Next( Next( IsCreateDb = result = (_context.db == = Db.Context(App.DefaultConnectionName??= ( i = ; i < qty; i++= ( rule += (_context.CurrentCode.Length > ? _context.SequenceDelimiter : .Empty)
++= (result.Length > ? : .Empty) + }
SequenceContext.cs
IDbContext db { ; ISequenceReset SequenceReset { ; List<SequenceRuleBase> Rules { ; TenantID { ; SequenceName { ; SequenceDelimiter { ; Step { ; CurrentNo { ;
CurrentCode { ; CurrentReset { ; IsMultipleTenant { ; Dictionary<,> row { ; = = = List<SequenceRuleBase>= = = CurrentNo = = = = Dictionary<, >
SequenceResetFactory.cs
ISequenceReset CreateReset( ( type ==> t.GetInterface()!= && t.Name.Equals(sequenceReset + (type == Exception(.Format(
ISequenceReset.cs
DateSequenceReset.cs
DateTime.Now.ToString(
NullSequenceReset.cs
PaddingSide.cs
SequenceRuleFactory.cs
SequenceRuleBase CreateRule( type ==> t.BaseType == (SequenceRuleBase) && t.Name.Equals(ruleName + (type == Exception(.Format(
SequenceRuleBase.cs
PaddingWidth { ; PaddingChar { ; PaddingSide PaddingSide { ; RuleValue { ; = = == result == result ?? (PaddingSide == PaddingSide.Left && PaddingWidth > (PaddingChar == Exception(.Format(= (PaddingSide == PaddingSide.Right && PaddingWidth > (PaddingChar == Exception(.Format(=
ConstSequenceRule.cs
RuleValue ??
GuidSequenceRule.cs
NumberingSequenceRule.cs
= data.CurrentNo + data.Setp
SQLSequenceRule.cs
data.db.Sql(RuleValue).QuerySingle<>
TimeStampSequenceRule.cs
IClassSequenceHandler.cs
ClassSequenceRule.cs
(handler == type = (type == Exception(.Format( (type.GetInterface() == Exception(.Format(=
GoodsNoSequenceRule.cs 商品編碼自定義處理示例
(!data.row.ContainsKey( Exception( (!data.row.ContainsKey( Exception( (!data.row.ContainsKey( Exception( list = List<> .Join(
a、配置單據規則表sys_sequence
b、根據需求配置租戶單據規則表sys_sequencetenant
c、配置編碼規則表
基礎規則包括:
1、const 常量
2、numbering 計數
3、timestamp 時間戳
4、guid GUID
5、sql SQL文
6、class 自定義類
你可以用這些基礎規則自由組合,當然也可以自己拓展基礎規則
使用很簡單
1、取得Ioc容器中的SequenceFactory對象
2、Factory創建具體的Sequence
3、調用Sequence的Next方法
如果不使用Ioc可能更簡單,直接
var result = new Sequence(name).Next();
代碼就這樣就行,然後可以通過配置改變各單據的業務編碼規則。
1、采購訂單,在這個頁面點擊新增按鈕
這個未保存的表單已經取得一個采購單號:CG20140505002 = (CG + 20140505 + 002)
2、保存後生成
編輯保存後,即按傳入的數據貨號 顏色 尺寸 生成了一個自定義的商品編碼 171240404781-W-XL
當然還有很多其它業務規則,大家都可以通過配置實現
一直在項目中忙著都沒動彈過,晚上抽空寫了篇博客,只是把我自己的想法實現出來,如果大家感興趣可以幫我推薦下,關於編碼規則這塊設計大家有沒有什麼更好的想法,也歡迎大家討論。
.NET框架交流群(四) 294214497