.NET:可扩展的单据编号生成器 之 基于缓冲区的顺序号
2013-05-14 08:39
323 查看
背景
我在上篇文章“.NET:可扩展的单据编号生成器 之 顺序号(防止重复)”中介绍了如何使用“种子表”和“悲观锁”解决顺序号的问题。昨天找朋友讨论,说这种速度不够高,今天就稍微改进一下,引入一个内存缓冲区,提高生成的速度。思路
引入内存缓冲区后,顺序号的生产流程变为:在内存中维护一个顺序号区间,在这个区间内,就直接查内存,否则更新种子表并重新更新内存区间。还是直接看代码吧。实现
代码下载:http://yunpan.cn/Q5jj5yedRAtk5。
SeedCodeRuleProvider.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Transactions; using System.Text.RegularExpressions; using System.Data.Entity.Infrastructure; namespace EntityCodeRuleDemo { public class SeedCodeRuleProvider : ICodeRuleProvider { private static readonly int _OnceBufferSize = 10000; private static readonly Dictionary<string, BufferSeed> _Buffer = new Dictionary<string, BufferSeed>(); private readonly int _width; public SeedCodeRuleProvider(int width) { _width = width; } public string Generate(object entity) { return GetSeedValue(entity).ToString().PadLeft(_width, '0'); } protected virtual string GetKey(object entity) { return entity.GetType().FullName; } private int GetSeedValue(object entity) { var key = this.GetKey(entity); lock (_Buffer) { if (!_Buffer.ContainsKey(key)) { this.SetBufferSeed(entity, key); } } lock (_Buffer[key]) { if (_Buffer[key].IsOverflow()) { this.SetBufferSeed(entity, key); } _Buffer[key].CurrentValue++; return _Buffer[key].CurrentValue; } } private void SetBufferSeed(object entity, string key) { var value = this.GetOrSetSeedValueFormDatabase(entity); _Buffer[key] = new BufferSeed { CurrentValue = value - _OnceBufferSize, MaxValue = value }; } private int GetOrSetSeedValueFormDatabase(object entity) { var key = this.GetKey(entity); try { using (var ts = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions { IsolationLevel = IsolationLevel.RepeatableRead })) { var value = 0; using (var context = new TestContext()) { var seed = context.CodeSeeds.Where(x => x.Key == key).FirstOrDefault(); if (seed == null) { seed = new CodeSeed { Id = Guid.NewGuid(), Key = key, Value = -1 }; context.CodeSeeds.Add(seed); } seed.Value += _OnceBufferSize; context.SaveChanges(); value = seed.Value; } ts.Complete(); return value; } } catch (DbUpdateException) { return this.GetSeedValue(entity); } } public static SeedCodeRuleProvider SeedCodeRuleProviderFactory(string literal) { var match = new Regex("^<种子(:(?<宽度>.*?))?>$").Match(literal); var width = match.Groups["宽度"].Value; return new SeedCodeRuleProvider(string.IsNullOrEmpty(width) ? 5 : int.Parse(width)); } private class BufferSeed { public int CurrentValue { get; set; } public int MaxValue { get; set; } public bool IsOverflow() { return this.CurrentValue >= this.MaxValue; } } } }
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; using System.Text.RegularExpressions; namespace EntityCodeRuleDemo { class Program { static void Main(string[] args) { CodeRuleInterpreter.RegistProviderFactory(new Regex("^<种子(:(?<宽度>.*?))?>$"), SeedCodeRuleProvider.SeedCodeRuleProviderFactory); var generator = CodeRuleInterpreter .Interpret("前缀_<日期:yyyy_MM_dd>_<属性:NamePinYin>_<种子:6>"); var watch = Stopwatch.StartNew(); for (var i = 0; i < 10000; i++) { generator.Generate(new Employee { NamePinYin = "DUANGW" }); } watch.Stop(); Console.WriteLine("1万条编号用时:" + watch.Elapsed); } } }
执行结果
备注
优化前后,速度相差几百倍。相关文章推荐
- .NET:可扩展的单据编号生成器 之 基于缓冲区的顺序号
- .NET:可扩展的单据编号生成器 之 顺序号(防止重复)
- .Net可扩展的单据编号生成器-SNF.CodeRule--SNF快速开发平台3.2
- .NET:可扩展的单据编号生成器 + 简单的解释器
- 一起谈.NET技术,基于CallContextInitializer的WCF扩展导致的严重问题
- 基于.NET 2.0的GIS开源项目SharpMap分析手记(八):怎样对SharpMap进行扩展开发——从许可角度来谈
- 基于.NET 2.0的GIS开源项目SharpMap分析手记(六):SharpMap的功能扩展之路
- .NET平台自带的AOP机制 转自《设计模式--基于c#的工程化实现及扩展》
- 基于.net的可扩展框架设计 - AppEx及相关接口
- [Open Source] .NET 基于StackExchange.Redis的扩展
- 基于.NET 2.0的GIS开源项目SharpMap分析手记(六):SharpMap的功能扩展之路
- 幸福框架:可扩展的、动态的、万能的 编号生成器
- 幸福框架:如何扩展编号生成器
- vs2008中让基于.net 2.0的应用程序也可以使用扩展方法
- 幸福框架:可扩展的、动态的、万能的 编号生成器
- 基于.NET 2.0的GIS开源项目SharpMap分析手记(八):怎样对SharpMap进行扩展开发——从许可角度来谈
- 数据生成器Bogus的使用以及基于声明的扩展
- 基于.net的可扩展框架设计 - 主体思路
- 基于.net的可扩展框架设计 - 动态代理
- 基于.net的可扩展框架设计 - 整体架构