Wie generieren Sie eindeutige Bestellnummer?
Ich bin auf der Suche nach eine gute Möglichkeit zum generieren eines eindeutigen Auftrags-ID. Sehen Sie irgendwelche Probleme mit dem code unten?
int customerId = 10000000;
long ticks = DateTime.UtcNow.Ticks;
long orderId = customerId + ticks;
int orderNumber = orderId.GetHashCode();
Ich gehe, um zu überprüfen, dass die Nummer eindeutig ist, in der Datenbank vor anlegen der Bestellung.
- Rein theoretisch, Hashwerte kollidieren können.
- Sicherlich ist es nicht wirklich einzigartig, die Sie suchen, einfach die nächste fortlaufende Nummer... ich Stimme mit der folk unten sprechen über die Verwendung einer identity-Spalte.
- Kunst: Nichts theoretisches über es. Hashwerte kollidieren die ganze Zeit. Es gibt nur rund vier Milliarden Euro zur Verfügung, so dass Sie natürlich dabei sind, zu kollidieren.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie speichern Ihre Datensätze in einer Datenbank, sollten Sie wirklich einen Blick in die verfügbaren Kapazitäten dort zu generieren eindeutiger Surrogat-Schlüssel. In SQL Server wäre dies eine IDENTITÄT Feld und in Oracle wäre es ein Feld, das verwendet SEQUENZ erzeugen Sie einen neuen Wert ein.
Wenn es einen zwingenden Grund, warum Sie nicht verwenden können Sie Ihre Datenbank einen eindeutigen Schlüssel generieren, sollten Sie schauen, etwas wie ein
Guid
- die mucher höhere Wahrscheinlichkeit als Datum-Zeit-manipulation generiert einen eindeutigen Wert. Guids werden kann trivial konvertiert in strings, also deine id wäre ein string in diesem Fall., Wie Sie mit den hashes ist nicht eine gute Idee - nichts gaurantees, dass hashes einzigartig sein wird - und in vielen Fällen tun Sie in der Tat kollidieren. Guids - nicht eine 100% Garantie der Einzigartigkeit über Maschinen aber auf einer einzigen Maschine, die Sie sollten immer eindeutig sein. Und auch über Maschinen, Ihre Chancen der Kollision sind äußerst gering. Auch, mit Computer-Zeit, als ein Weg zum Aufbau der zugrunde liegende Wert unterliegt race-Bedingungen (wie den Eric beschreibt).
Guids sind 128-bit-Werte, so kann man nicht vertreten, als eine einfache
int
oderlong
. Es würde erfordern, dass Sie die Verwendung von string als Ihre IDs -, die möglicherweise oder möglicherweise nicht möglich sein, in Ihrem Fall, je nach anderen überlegungen (wie, ob oder nicht Sie Steuern die Daten-Modell). Wenn Sie verwenden können, mithilfe einer Guid ist wirklich einfach:Wenn Sie wirklich müssen, verwenden Sie eine numerische Kennung, und Sie sind bereit zu verzichten, einfach die Skalierung Ihrer Anwendung auf mehreren Servern, Sie können einen auto-increment global-Reihe liefern einen einzigartigen Schlüssel. Sie hätten die Samen dieser Zahl mit der nächsten verfügbaren Wert (max+1) aus Ihrer Datenbank, wenn die Anwendung startet. Sie müsste auch dann schützen Sie diesen Wert aus der gleichzeitigen Verwendung von mehreren threads. Ich würde wickeln Sie diese Verantwortung in einer Klasse:
EDIT: In diesem Tag und Alter, dass zwingende Gründe für die Erzeugung von eindeutigen IDs in Ihre Anwendung Ebene anstatt auf der Datenbank sind sehr selten. Sie sollten wirklich die Funktionen, die die Datenbank bietet.
Angenommen, Sie haben zwei Kunden-ids, die sich durch 100, und Sie passieren, beide machen eine Bestellung, die 100 Einheiten auseinander. Ihre Einzigartigkeit ging einfach aus dem Fenster.
Du sagen, du gehst zum überprüfen der Datenbank für die Einzigartigkeit; Sie sagen nicht, was Sie tun werden, wenn es zu einer Kollision. Sie müssen auch nicht sagen, was wirst du tun, um race conditions; nehmen wir an, zwei kollidierenden Bestell-ids erstellt werden, zur gleichen Zeit, weder in der Datenbank. Fragen Sie die Datenbank auf zwei verschiedenen threads, ob das Element ist einzigartig; es ist. Geben Sie dann beides, und die Eindeutigkeit verletzt wurde, obwohl der check wurde durchgeführt.
Dies ist ein wirklich, wirklich schlechter Weg, um Einzigartigkeit. Was besser wäre ist, verschieben Sie diese in die Datenbank-Schicht. Sie pflegen einen globalen, threadsicher Zähler der Aufträge und ordnen Sie jedem neuen Auftrag die nächsthöhere Nummer der Bestellung.
Übrigens, für viele Jahre habe ich gefragt, eine variation auf diese Frage als eine technische interview-Frage. Ich habe bemerkt, eine starke Korrelation zwischen der Menge der Menschen, die versuchen, zu verwenden die Zeit als Quelle der Einzigartigkeit und der Gruppe von Menschen, die nicht angeheuert. Zeit ist ein schrecklichen Quelle von Einzigartigkeit; viele verschiedene Dinge können gleichzeitig geschehen.
Was noch schlimmer ist, ist die Verwendung von Zufallszahlen. Zufallszahlen sind eine noch schlechtere Quelle von Einzigartigkeit, als timestamps. Angenommen, Sie haben eine wirklich random number generator erzeugt zufällige 32-bit-Ganzzahlen für die Auftrags-IDs. Wie viele Aufträge brauchen Sie zu haben, bevor die Chancen stehen besser als fünfzig zu fünfzig, dass Sie erstellt haben, zwei Aufträge mit der gleichen ID? Die Antwort überrascht viele Leute: es ist nur etwa 77 tausend, bevor es eine chance von 50%, die Sie erstellt haben, zwei Aufträge mit der gleichen Anzahl (und nur 9300, bis es gibt eine 1% chance.)
Denken Sie daran: was Sie nach ist eine Garantie Einzigartigkeit. Nicht ein wahrscheinlich Einzigartigkeit, aber eine eiserne Garantie, dass eine Bestell-Nummer bezieht sich auf genau eine Bestellung. Wenn es das ist, was Sie brauchen, dann stellen Sie sicher, Sie umzusetzen.
Was ist mit einem id-Feld in der Datenbank für Sie tun?
Wird es auch den Vorteil, dass die gelöschten/stornierten Auftrag Nummern nicht wiederverwendet werden (was gut ist, oder kann sogar notwendig sein, für die Buchhaltung).
WENN Sie SQL Server verwenden, sollten Sie wirklich nachschlagen den IDENTITÄT Spezifikation. Es können Sie tun dies mit Leichtigkeit und Geschwindigkeit.
Ihre Lösung ist nicht eindeutig, da können Dinge passieren, die so schnell in dem system, das zwei Prozesse laufen, entweder nacheinander oder gleichzeitig, kann die gleiche tick-Wert.
Ich würde verwenden Sie die IDENTITY-Spalte und wenn nicht, verwenden Sie System.Guid.NewGuid() zum erzeugen einer GUID für Sie.
Sehen Knuth Vol. 2 Chap 3 auf Zufallszahlen