随笔 - 24  文章 - 0 评论 - 19 阅读 - 41681
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

数据库中的一条记录,除了应有自己的唯一切不包含任何逻辑意义的主键外,常常也需要一些暴露给最终用户的,User-Friendly的唯一编号。

 

例如用户、订单之类的对象,除了自己有一个可能是GUID类型的主键以外,常常还会有一个Int型的编号“用户编号”,“订单号码”。

 

如果直接操作数据库,例如SQL SERVER,这是很容易的,只需要将字段设成Identity即可获得一个自增量。

 

但是在XPO中,只有作为KEY(主键)的字段才有AutoGenerate属性,其他非KEY的字段都没有。同时,XPO又限定一个对象只能有一个KEY字段。(实际上System.Data.SqlClient也是不支持的)

 

那如何获取一个自增量?只能靠自己动手了。

 

DevExpress的Support Center中提供了一段Sample:

http://www.devexpress.com/Support/Center/p/CQ22273.aspx

 

例子中的代码稍显复杂,偶将其简化如下:

复制代码
XpoSequencer
 1     public sealed class XpoSequencer : XPBaseObject
 2     {
 3         [Key(true)]
 4         public Guid Oid;
 5         [Size(254), Indexed(Unique = true)]
 6         public string SequenceId;
 7         public int Counter;
 8         public XpoSequencer(Session session) : base(session) { }
 9         public const int MaxIdGenerationAttempts = 7;
10         public const int MinConflictDelay = 50;
11         public const int MaxConflictDelay = 500;
12 
13         public static int GetNextValue(IDataLayer dataLayer, string sequenceId)
14         {
15             if (dataLayer == null)
16                 throw new ArgumentNullException("dataLayer");
17             if (sequenceId == null)
18                 sequenceId = string.Empty;
19             for (int attempt = 1; ; ++attempt)
20             {
21                 try
22                 {
23                     using (Session generatorSession = new Session(dataLayer))
24                     {
25                         XpoSequencer generator = generatorSession.FindObject<XpoSequencer>(new OperandProperty("SequenceId"== sequenceId);
26                         if (generator == null)
27                         {
28                             generator = new XpoSequencer(generatorSession);
29                             generator.SequenceId = sequenceId;
30                         }
31                         generator.Counter++;
32                         generator.Save();
33                         return generator.Counter;
34                     }
35                 }
36                 catch (LockingException)
37                 {
38                     if (attempt >= MaxIdGenerationAttempts)
39                         throw;
40                 }
41                 if (attempt > MaxIdGenerationAttempts / 2)
42                     Thread.Sleep(new Random().Next(MinConflictDelay, MaxConflictDelay));
43             }
44         }
45     }
复制代码

 

 

只需要上面这个XpoSequencer类即可,例子中的XpoSiteId类偶没用。

 

XpoSequencer 类的使用方法也很简单,例如在Order类中需要获取一个自增订单号:

        static readonly string typeName = typeof(XpoOrder).FullName;

        
int GetMaxID()
        {
            
return (int)XpoSequencer.GetNextValue(Session.DataLayer, typeName);
        }

 

 

注意上面的typeName字符串,它代表了要获取自增量对象的唯一标识。在XpoSequencer中会对每一个唯一标识添加一条记录,自增量是按该记录中的值来算的。在一个项目中就可以用XpoSequencer为多个对象产生各自独立的自增量。例如换到User要用时,传入typeof(XpoUser).FullName即可。也可以用其他的任意字符串,只要能唯一的标识出不同的自增量就可以。

 

posted on   Elvin Chen  阅读(898)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示