随笔 - 49  文章 - 0 评论 - 205 trackbacks - 6
<2008年2月>
272829303112
3456789
10111213141516
17181920212223
2425262728291
2345678

严正声明 : 本站文章转载请注明出处.

与我联系

搜索

 

留言簿(11)

我的标签

随笔分类

随笔档案

Atlas相关

积分与排名

  • 积分 - 55159
  • 排名 - 761

阅读排行榜

有时候可以在别的网站上看到类似于这样的ID : D6pPMSTjOFI, 关于数据库主键的选择园子里面也讨论过许多了,比如这篇 小议数据库主键选取策略(原创). 字符串作ID有时候还是有它的优点的,但是如何生成不重复且易于生成按索引顺序排列的ID呢.  原来我是用的 DateTime.Now.Ticks 可以产生一个long类型的时间刻度值,后来要用字符串的,就把这个转成16进制的, 当然也可以工作,但是似乎还是太长了一点,于是想到能不能创建自己的"进制数"呢,按unicode的编码, 从小到大应该是数字, 大写字符,小写字符,把它们放在一起可以形成一个62元素的数组,这就可以构成一个"62进制"的数了.

不过没有看.net框架里面的进制转换实现方案,本人不才自己写了一个来玩, 目前看来还可以工作, 有兴趣的高手看看可以怎么改进改进. 可以将int, uint, long, ulong(暂不支持负数转换)转换成字符型的值. 算法不是很难,因为ulong的最大值只需要11位的字符串就可以表示了因此结果采用一个11元素的字符串数组来装, 首先确定转换出来的数有几个位数,接着按从高到低的数位进行计算, 比如10进制里面的 520 = 5*10*10 + 2*10 + 0 , 因此计算过一位的值之后减去它再计算下一位的值,采用递归调用直到最低位.然后将字符串数组拼装成完整字符返回就完成了.

采用时间刻度生成的ID应该可以按索引顺序插入吧,会不会出现GUID那样数据越多,插入越慢的情况? 我觉得不会, 有待数据库专家论证.

要反向转换就比较容易了,代码就不再给出.

代码如下,

Code

再附上单元测试 :

Code

在沙加的神舟本上完成的单元测试控制台输出:






posted on 2008-02-15 17:36 沙加 阅读(1147) 评论(6)  编辑 收藏 所属分类: .Net开发技巧系列

FeedBack:
#1楼  2008-02-15 18:57 Anders Liu      
用了不少乘法,效率……
  回复  引用  查看    
#2楼 [楼主] 2008-02-15 19:36 沙加      
@Anders Liu
谢谢,这个问题之前也考虑过,要省时间可以用数组先全部算出来放在那里. 生成ID只是插入记录的时候使用,暂时没有做优化.
  回复  引用  查看    
#3楼  2008-02-15 20:07 83rrr [未注册用户]
非常不错,用了很好
  回复  引用    
#4楼  2008-02-15 20:46 双鱼座      
这代码质量真不敢恭维啊!
// if (desCode.Length != 11 || orgin < 0)
ulong orgin永远都不会 < 0。

既然确定是进制转换,当然是用取余了:

private static string ToString(ulong arg)
{
ulong mod = 62L;
StringBuilder line = new StringBuilder();
while (arg > 0)
{
line.Insert(0, charactor[arg % mod]);
arg /= mod;
}
return line.ToString();
}

  回复  引用  查看    
#5楼 [楼主] 2008-02-15 21:04 沙加      
@双鱼座
仓促成文,多谢指正.
  回复  引用  查看    
#6楼  2008-03-08 13:06 finull      
--引用--------------------------------------------------
双鱼座: 这代码质量真不敢恭维啊!
// if (desCode.Length != 11 || orgin < 0)
ulong orgin永远都不会 < 0。
既然确定是进制转换,当然是用取余了:
private static string ToString(ulong arg)
{
  ulong mod = 62L;
  StringBuilder line = new StringBuilder();
  while (arg > 0)
  {
    line.Insert(0, charactor[arg % mod]);
    arg /= mod;
  }
  return line.ToString();
}
--------------------------------------------------------
当arg=0时,你返回的是空值...
改成
  while (arg > 61)
  {
    line.Insert(0, charactor[arg % mod]);
    arg /= mod;
  }
  line.Insert(0, arg);
就可以了
  回复  引用  查看    

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-02-15 21:30 编辑过