2010-12-12 3 views
5

Ich muss 8-stellige eindeutige ID in C# generieren. Auf meiner Website wird ein Benutzer registriert und ich muss eine eindeutige ID für ihn in C# -Code generieren (ich will diese Logik in DB nicht), nach dem Einfügen der ID muss ich es in der Datenbank speichern.Erzeuge 8-stellige Uinque-ID in C#

Edit: Ich brauche diese Zahlen in zufälliger Weise jedes Mal generiert werden.

+5

Können Sie erklären, warum Sie in der DB dagegen sind? – Oded

Antwort

11

Obwohl nicht 8 Ziffern, ich GUID zu diesem Zweck verwenden würde:

var id = Guid.NewGuid().ToString() 

Aus Wikipedia:

Idealerweise wird eine GUID niemals von jeder zweimal erzeugt Computer oder Gruppe von Computern existiert. Die Gesamtanzahl der eindeutigen Schlüssel (2^128 oder 3,4 × 10^38 - in Relation gibt es etwa 1,33 × 10^50 Atome auf der Erde) ist so groß, dass die Wahrscheinlichkeit der gleichen Nummer zweimal extrem ist kleine und bestimmte Techniken wurden entwickelt um sicherzustellen, dass die Zahlen nicht dupliziert werden

+2

'Wahrscheinlichkeit der gleichen Anzahl wird zweimal generiert ist extrem klein' aber nicht 0 –

+2

Sie haben Recht - aber es ist völlig sicher, GUIDs für dieser Zweck. Microsoft verwendet sogar GUIDs als Primärschlüssel der Datenbanktabelle. –

2

Warum nicht einfach die letzte zugewiesene Nummer behalten und sie beim Zuweisen einer neuen ID um 1 erhöhen? Interlocked.Increment könnte nützlich sein. Sie können die Nummer mit Nullen links auf die 8 Ziffern auffüllen. Die Verwendung von int als Backing-Typ sollte ausreichen.

Edit: wenn Sie die Nummer wollen zufällig aussehen, speichert nur in der DB nicht die zugewiesenen laufenden Nummern selbst, sondern eine bijektive Abbildung verwenden. Zum Beispiel können Sie stattdessen 7461873*ID + 17845612 speichern. Dies garantiert die Einzigartigkeit und sieht zufällig aus.

Übrigens ist das ähnlich, wie die Zufallsgeneratoren normalerweise arbeiten (nur sie verwenden nicht die laufende Nummer, sondern das Ergebnis der vorherigen Berechnung).

+0

Nicht den Wunsch des OP nach Zufälligkeit adressieren, aber für jeden, der nach sequentiellen Zahlen wie @Vlads ursprünglichem Vorschlag sucht, wird etwas wie folgt tun: 'private static int _sequentialNum = 0; private Zeichenfolge GetNextNumber() {return Interlocked.Increment (ref _sequentialNum) .ToString ("d8"); } '. Die Increment-Methode wird bei Int32.MaxValue umbrochen. Wenn Sie Wert auf negative und große Zahlen legen, verwenden Sie Interlocked.Exchange, um bei Bedarf auf 0 zurückzusetzen. – Rory

3

Wenn es Ihnen nichts ausmacht, dass die IDs vorhersehbar sind, würde ich mit Vlads Vorschlag gehen.

Sonst würde ich eine Zufallszahl im erforderlichen Bereich generieren und nur versuchen, in die Datenbank einfügen ... wenn Sie eine Ausnahme wegen der Eindeutigkeit Einschränkung in der Datenbank verletzt werden (und diese Einschränkung sollte unbedingt da sein) dann versuch es nochmal. Versuche es weiter, bis es entweder funktioniert oder du eine bestimmte Anzahl von Malen durchlaufen hast. (Es ist sehr unwahrscheinlich, dass Sie zum Beispiel 100 Mal scheitern werden - es sei denn, Sie haben einen Fehler an einer Endlosschleife.)

Das ist also nicht Generierung der die ID in der Datenbank - aber es überprüft die Einzigartigkeit in der Datenbank, die schließlich die ultimative "Quelle der Wahrheit" ist.

Wenn Sie keine kryptografisch sicher generierten IDs benötigen, generiert Ihnen die einfache Verwendung von Random.Next(100000000) einen Wert im Bereich [0, 99999999]. Wenn Sie keine Werte wünschen, die führende Nullen benötigen, um 8 Stellen zu erhalten, verwenden Sie einfach Random.Next(10000000, 100000000), was Ihnen einen kleineren Bereich möglicher Werte gibt, aber Sie müssen sich keine Sorgen machen, dass sie weniger als 8 Ziffern haben.

Verwenden Random richtig hat ein paar "Gotchas" - siehe meine article about it für weitere Details.

+0

Wenn die Nummer "unvorhersehbar" sein muss, würde ich die kombinierte Lösung wählen: halte die "echte" Zahl einfach jeweils um 1 erhöht und ordne sie einer "unvorhersehbaren" Darstellung zu, indem du eine Eins-zu-Eins-Abbildung von [ 0..99999999] auf sich selbst. Ein Beispiel für eine solche Abbildung ist "x -> (N * x + M) mod 10^8", wobei "gcd (N, 10^8) == 1)". Der Vorteil dieses Ansatzes ist keine Notwendigkeit zu versuchen. – Vlad

+0

@Vlad: Das beruht auf Sicherheit durch Dunkelheit - d. H. Dass Ihr Algorithmus nicht bekannt ist. –

+0

kein zufälliger rein Code-basierter Generator ist wirklich zufällig (außer dass er einige physikalische Prozesse verwendet, die für die Online-Analyse nicht verfügbar sind), so dass die Verwendung des Zufallszahlengenerators keine wirklich bessere Sicherheit garantiert. – Vlad

1

können Sie verwenden Random Class

Random r=new Rand(); 
int id; 
while((id=r.Next(10000000,99999999))!=someId); //check in database that Id is unique 

Denken Sie immer daran, dass es keine Technik ist eine eindeutige Zufallszahl ohne zu prüfen, vorhandene Werte in der Datenbank

Sie müssen einige Informationen zu früheren Werten

zu erzeugen
+0

warum nicht? Meine Antwort gibt ein Beispiel, wie dies erreicht werden kann, ohne die Datenbank abzufragen. – Vlad

+1

@Vlad, ich meine, dass vorherige Werte und Sie auch für früheren Wert erinnern müssen –

1

Sie könnten versuchen, eine Methode zu implementieren, die eine Zufallszahl generiert, aber Sie müssen immer überprüfen, ob es bereits in der Datenbank ist.

static void Main(string[] args) 
    { 
     HashSet<string> numbers = new HashSet<string>(); 

     for (int i = 0; i < 100; i++) 
     { 
      numbers.Add(GenerateRandomNumber(8)); 
     } 

     Console.WriteLine(numbers.Count == 100); 
     Console.ReadLine(); 
    } 

    static Random random = new Random(); 

    static string GenerateRandomNumber(int count) 
    { 
     StringBuilder builder = new StringBuilder(); 

     for (int i = 0; i < count; i++) 
     { 
      int number = random.Next(10); 
      builder.Append(number); 
     } 

     return builder.ToString(); 
    } 
1

Benutze Sequenzielle Guids! Reduziert die Wahrscheinlichkeit eines Konflikts, bei dem die Wahrscheinlichkeit einer Kollision von Guids sehr gering ist, und bedeutet auch, dass Sie Ihre Daten nach Guid ordnen können, was den Zeitpunkt des Einfügens darstellt.

[DllImport("rpcrt4.dll", SetLastError = true)] 
    static extern int UuidCreateSequential(out Guid guid); 

    public static Guid SequentialGuid() 
    { 
     const int rpcSOk = 0; 
     Guid guid; 

     return UuidCreateSequential(out guid) != rpcSOk ? Guid.NewGuid() : guid; 
    } 

Sie können für die Kunden diese Methode in der Basisklasse setzen, oder alle Unternehmen und haben es automatisch im Basiskonstruktor auf instatiation erzeugt.

0

Sie können auch meinen Kennungsgenerator verwenden. Aber es ist leider kein Integer. Stellen Sie sicher, dass Sie die Groß-/Kleinschreibung in ID-Spalte in db ändern, andernfalls ändern Sie den Zeichenbereich. Der Bezeichner ist URL freundlich. Basiert auf partiellen DateTime Ticks (10 Zeichen) und partiellen Random (6 Zeichen). Es ist nicht sortierbar. Verwenden Sie stattdessen die AddedDate-Spalte, um eine Zeilensequenz zu erhalten. Verwenden Sie varchar(16) Spalte Typ und SQL_Latin1_General_CP1_CS_AS Kollation.

public static class IdentifyGenerator 
{ 
    private static char[] sybmols = { 
          '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
          'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 
         'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 
         }; 

    public static string WebHash() 
    { 
     int length = sybmols.Length; 
     ulong num = (ulong)DateTime.Now.Ticks; 

     string output = string.Empty; 
     ulong tmp = num; 
     ulong mod = 0; 
     while (tmp != 0) 
     { 
      mod = tmp % (ulong)length; 
      tmp = tmp/(ulong)length; 
      output = sybmols[mod] + output; 
     } 
     output += RandomString(6); 
     return output; 
    } 

    public static string RandomString(int length) 
    { 
     Stack<byte> bytes = new Stack<byte>(); 
     string output = string.Empty; 

     for (int i = 0; i < length; i++) 
     { 
      if (bytes.Count == 0) 
      { 
       bytes = new Stack<byte>(Guid.NewGuid().ToByteArray()); 
      } 
      byte pop = bytes.Pop(); 
      output += sybmols[(int)pop % sybmols.Length]; 
     } 
     return output; 
    } 
} 

Einheit Test:

[TestClass] 
public class Code 
{ 
    [TestMethod] 
    public void IdentifyGeneratorTest() 
    { 
     var set = new HashSet<string>(); 
     for (int i = 1; i <= 1000000; i++) 
     { 
      var id = IdentifyGenerator.WebHash(); 
      if (!set.Add(id)) 
       Assert.Fail("IdentifyGenerator duplicate found"); 
     } 
    } 
} 

Viel Glück.

+0

Warum 'RandomString (6)'? auch 'IdentifyGenerator.WebHash()' erzeugt eine Zeichenkette der Länge '16' nicht' 8'. –