views:

138

answers:

3

One requirement is that when persisting my C# objects to the database I must decide the database ID (surrogate primary key) in code.

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.

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". These are easily created in code and are to me acceptable in URLs if necessary. But will it be too expensive regarding performance (indexing, size) having all primary and foreign keys be 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.

A: 

A simple incrementing int would be the easiest way to ensure uniqueness. 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.

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. 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.

rikh
A: 

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!):

  • Assign each user a unique "UserID" in your database (can be INT, or CHAR)
  • Assign each user a "HighestSequentialID" (INT) in your database
  • When the user logs on, read those values from the database and store them in e.g. a custom principal, or in a cookie, or something else
  • whenever the user is about to insert a row, create a segmented ID: (UserID).(User's sequential number) and store it as "VARCHAR(20)" - e.g. your UserID is 15 and thus this user's entries would have unique IDs of "15.00001", "15.00002" and so on.
  • 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

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).

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

marc_s
+1  A: 

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.

Vilx-
And that's again on the database - which according to the OP, he can't touch when creating the unique ID's....
marc_s
Ah, well... then not, I guess. :P
Vilx-