如果您将记录存储在数据库中,您应该真正研究数据库中可用于生成唯一代理键的功能。在 SQLServer 中,这将是IDENTITY http://msdn.microsoft.com/en-us/library/aa933196%28SQL.80%29.aspx字段,在 Oracle 中它将是一个使用SEQUENCE http://www.techonthenet.com/oracle/sequences.php来产生新的价值。
如果有令人信服的原因导致您无法使用数据库生成唯一密钥,那么您应该查看类似Guid http://msdn.microsoft.com/en-us/library/system.guid.aspx- 比日期时间操作更有可能生成唯一值。指南可以简单地转换为字符串,因此在这种情况下您的标识符将是一个字符串。
你对哈希所做的事情不是一个好主意- 没有什么可以保证哈希值是唯一的 - 在许多情况下它们确实会发生冲突。指南 - 不提供 100% 的唯一性保证跨机器但在一台机器上它们应该始终是唯一的。即使是跨机器,它们发生碰撞的可能性也极小。此外,使用机器时间作为构建基础价值的方式会受到竞争条件的影响(就像埃里克所描述的那样)。
Guid 是 128 位值,因此您不能将它们表示为简单的int
or long
。它需要您使用字符串作为您的 ID,这在您的情况下可能可行,也可能不可能,具体取决于其他考虑因素(例如您是否控制数据模型)。如果可以使用它们,那么使用 Guid 就非常简单:
string customerId = Guid.NewGuid().ToString(); // fetch new guid and save as string
string orderNumber = Guid.NewGuid().ToString(); // same story here...
如果您确实必须使用数字标识符,并且愿意放弃在多个服务器之间轻松扩展应用程序,则可以使用自动递增的全局数字来提供唯一键。当应用程序启动时,您必须使用数据库中的下一个可用值 (max+1) 来播种该数字。然后,您还必须保护该值不被多个线程并发使用。我会将这个责任包装在一个类中:
class static UniqueIDGenerator
{
// reads Max+1 from DB on startup
private static long m_NextID = InitializeFromDatabase();
public static long GetNextID() { return Interlocked.Increment( ref m_NextID ); }
}
EDIT: 在当今时代,在应用程序层而不是在数据库中生成唯一 ID 的令人信服的理由非常罕见。您确实应该使用数据库提供的功能。