0

I'm searching for a primary key for CMS that I'm creating that not be in an ascending or descending sequence so I decided to use random numbers.

I want to use random numbers as PK and because of possibility of repetitive numbers;Is possible to giving an array of numbers that shouldn't be in next random generation ?

I'm not using any database.

Majid
  • 13,853
  • 15
  • 77
  • 113
  • 1
    If you're using a MYSQL database, there will never be two equal PKs if you use Auto-increment. – christopher May 03 '13 at 12:40
  • Not that I know of, you could create a method that generates a random number and checks it against a list of previously generated numbers before passing it on or generating a different one. – Kobunite May 03 '13 at 12:41
  • Using a randomizer (which has collisions frequently if the set size is small) is not a good way of getting a PK -use an auto-generated key if you're using a database -and if you're not then leverage a counter in a file that you **lock when you read and write.** – Mike Perrenoud May 03 '13 at 12:42
  • 3
    Let the database handle the unicity ! You're certainly not as good as the developers of it. If you don't use databases, then use GUID as unique identifier... – Laurent S. May 03 '13 at 12:42
  • was just about to say the same, why not use GUIDs? the probably are random enough for you ;) – DrCopyPaste May 03 '13 at 12:43
  • @ChrisCooney I'm not using any database. – Majid May 03 '13 at 12:43
  • @DrCopyPaste, as long as the data isn't shared amongst machines then a `Guid` may work -but there are some inherent problems with them, not least of which is they are not statistically indexable. See, they too have a fairly significant collision rate for use as a PK (**for my liking**) -but I've seen a lot of people use them. – Mike Perrenoud May 03 '13 at 12:45
  • Actually, sequential numbers aren't needed here, but aren't a problem neither... why not simply re-implement the principle of a cursor ? – Laurent S. May 03 '13 at 12:48

3 Answers3

4

You could try Guid:

string guid = Guid.NewGuid().ToString("N");

From msdn:

A GUID is a 128-bit integer (16 bytes) that can be used across all computers and networks wherever a unique identifier is required. Such an identifier has a very low probability of being duplicated

An interesting link that is against counting and pro guids.

bitWorking
  • 12,485
  • 1
  • 32
  • 38
0

I have to say that I would recommend leveraging a text file if you're not using a database. In the text file would be a single value -the counter -and the code would look like this:

lock (_lockObj)
{
    var cntr = Convert.ToInt32(File.ReadAllText("path to counter file"));
    var newKey = cntr;
    cntr++
    File.WriteAllText("path to counter file", cntr.ToString());
}

where _lockObj is declared like this at the class scope:

private readonly object _lockObj = new Object();

One note here is that the class you get the counter from needs to be a Singleton because you don't want to have more than one _lockObj.


On another note, if you are going to share this amongst users you will want to make this class accessible via a service that all of them share (e.g. web service) so that when you lock the file they are all locking against the same lock object and thus waiting for each other.

Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
0

Whether you're using a database (which I would strongly recommend), or a text-file, or something else, there is the problem of checking new keys against used keys; this will not be a problem at first, since you will have few used keys to begin with. If you add a lot of numbers though, validating a new key will take more time, as there will be more keys to compare to.

You could solve this by generating all the keys once, to begin with, and delete used keys (or mark them as used) each time a key is used.

Without getting to specific about the details: You could for instance generate 500'000 rows (or more) in a table, and include a row-number, a PK, and a field marking a row as "used". When you need a new key, select the PK from a random row, and mark that row as used (or delete it, if you prefer).

If you use a text-file, you could do the same, making sure to delete each "picked" line as you go.

Kjartan
  • 18,591
  • 15
  • 71
  • 96