简体   繁体   English

在代码中生成唯一的数据库ID

[英]Generating unique database IDs in code

One requirement is that when persisting my C# objects to the database I must decide the database ID (surrogate primary key) in code. 一个要求是,将C#对象持久保存到数据库时,我必须在代码中确定数据库ID(代理主键)。

Second requirement is that the database type for the key must be int or char(x)... so no uniqueidentifier or binary(16) or the like. 第二个要求是,密钥的数据库类型必须为int或char(x)...,因此不能使用uniqueidentifier或binary(16)等。

These are unchangeable requirements. 这些是不可更改的要求。

What would be the best way to go about handling this? 处理此问题的最佳方法是什么?

One idea is the base64 encoded GUIDs looking like "XSiZtdXcKU68QWe7N96Dig". 一种想法是base64编码的GUID,看起来像“ XSiZtdXcKU68QWe7N96Dig”。 These are easily created in code and are to me acceptable in URLs if necessary. 这些很容易用代码创建,如果需要的话,对我来说URL也可以接受。 But will it be too expensive regarding performance (indexing, size) having all primary and foreign keys be char(22)? 但是,对于具有所有主键和外键都为char(22)的性能(索引,大小),是否会过于昂贵? Off hand I really like this idea. 副手我真的很喜欢这个主意。

Another idea would be to create a code version of a database sequence creating incremented integers for me. 另一个想法是创建数据库序列的代码版本,为我创建增量整数。 But I don't know if this is plausible and would need some guidance to secure the reliability. 但是我不知道这是否合理,是否需要一些指导以确保可靠性。 The sequencer must know har far it has come and what about threads that I don't control etc. 音序器必须知道它已经远了,以及我不控制的线程等等。

I imagine that no table involved will ever exceed 1.000.000 rows... will probably be far less. 我想象没有涉及的表会超过1.000.000行...可能会少得多。

You could have a table called "sequences". 您可能有一个称为“序列”的表。 For each table there would be a row with a counter. 对于每个表,将有一个带有计数器的行。 Then, when you need another number, fetch it from the counter table and increment it. 然后,当您需要另一个数字时,请从计数器表中获取并递增。 Put it in a transaction and you will have uniqueness. 将其放在事务中,您将具有唯一性。

However this will suffer in terms of performance, of course. 但是,这当然会影响性能。

A simple incrementing int would be the easiest way to ensure uniqueness. 一个简单的int增量将是确保唯一性的最简单方法。 This is what the database will do if you let it. 如果您允许,数据库将执行此操作。 If you set the table row to auto_increment, the database will do this for you automatically. 如果将表行设置为auto_increment,则数据库将自动为您执行此操作。

There are no security issues with this, but since you will be handling it yourself instead of letting the database engine take care of it, you will need to ensure that you don't generate the same id twice. 这样做没有安全性问题,但是由于您将自己处理它而不是让数据库引擎来处理它,因此需要确保不会两次生成相同的ID。 This should be simple if you are on a single threaded system, but if your program is distributed you will need to put some effort into ensuring the uniqueness. 如果您使用的是单线程系统,这应该很简单,但是如果您的程序是分布式的,则需要付出一些努力来确保唯一性。

Seeing that you have an ASP.NET app, you could do the following (hoping and assuming all users must authenticate themselves before using your app!): 看到您拥有一个ASP.NET应用程序,您可以执行以下操作(希望并假设所有用户在使用您的应用程序之前都必须对自己进行身份验证!):

  • Assign each user a unique "UserID" in your database (can be INT, or CHAR) 在数据库中为每个用户分配一个唯一的“ UserID”(可以是INT或CHAR)
  • Assign each user a "HighestSequentialID" (INT) in your database 在数据库中为每个用户分配一个“ HighestSequentialID”(INT)
  • When the user logs on, read those values from the database and store them in eg a custom principal, or in a cookie, or something else 当用户登录时,从数据库中读取这些值并将其存储在例如自定义主体,Cookie或其他内容中
  • whenever the user is about to insert a row, create a segmented ID: (UserID).(User's sequential number) and store it as "VARCHAR(20)" - eg your UserID is 15 and thus this user's entries would have unique IDs of "15.00001", "15.00002" and so on. 每当用户将要插入一行时,创建一个分段ID:(UserID)。(用户的序号)并将其存储为“ VARCHAR(20)”-例如,您的UserID为15,因此该用户的条目将具有唯一的ID “ 15.00001”,“ 15.00002”,依此类推。
  • when the user logs off (or at any other time), update its new, highest used sequential ID in the database so that next time around, you'll know what this user has used last 当用户注销(或在任何其他时间)时,更新其在数据库中使用率最高的新顺序ID,以便下次知道该用户最后一次使用的内容

Again - you'll have to do a lot more housekeeping work yourself, and it's always prone to a mishap (assigning a duplicate user ID, or misinterpreting the highest sequential number for that user). 再说一次-您必须自己做更多的内务处理工作,并且总是很容易发生事故(分配重复的用户ID或误解该用户的最高序号)。

I would strongly recommend trying to get these requirements changed - with these in place, all solutions will be sub-optimal at best, while using the database to handle this would be totally painless. 我强烈建议您尝试更改这些要求-将这些要求放在适当的位置,所有解决方案充其量都将是次优的,而使用数据库来处理此问题将是完全轻松的。

Marc

For a table below 1.000.000 rows, I would not be too terribly concerned about a char(22) Primary key. 对于1.000.000行以下的表,我不会太在意char(22)主键。 Of course the ideal solution for a situation like this would be for each object to have something unique about it that you could leverage for the key, even if it is a multi-part key. 当然,对于这种情况,理想的解决方案是使每个对象都具有唯一的特征,即使该键是多部分键,也可以利用该键。 The next ideal solution would be to have the requirements changed :) 下一个理想的解决方案是更改需求:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM