Comment générer de numéro de commande unique?
Je suis à la recherche d'un bon moyen pour générer un unique numéro de commande. Pouvez-vous voir des problèmes avec le code ci-dessous?
int customerId = 10000000;
long ticks = DateTime.UtcNow.Ticks;
long orderId = customerId + ticks;
int orderNumber = orderId.GetHashCode();
Je vais vérifier que le numéro est unique dans la base de données avant la création de l'ordre.
Purement théoriquement, les hachages peuvent entrer en collision.
Assurément, il n'est pas vraiment unique vous êtes à la recherche pour, juste le prochain numéro séquentiel... je suis d'accord avec le folk-dessous de parler à l'aide d'une colonne d'identité.
Art: Rien de théorique. Les hachages de collision tous les temps. Il y a seulement environ quatre milliards de disponibles, alors, évidemment, ils vont entrer en collision.
Assurément, il n'est pas vraiment unique vous êtes à la recherche pour, juste le prochain numéro séquentiel... je suis d'accord avec le folk-dessous de parler à l'aide d'une colonne d'identité.
Art: Rien de théorique. Les hachages de collision tous les temps. Il y a seulement environ quatre milliards de disponibles, alors, évidemment, ils vont entrer en collision.
OriginalL'auteur Junior Developer | 2010-02-15
Vous devez vous connecter pour publier un commentaire.
Si vous êtes le stockage de vos documents dans une base de données, vous devriez vraiment regarder dans les capacités disponibles pour générer unique clés de substitution. Dans SQLServer ce serait un IDENTITÉ terrain et à l'Oracle qu'il serait un champ qui utilise un SÉQUENCE pour générer une nouvelle valeur.
Si il y a une raison convaincante pour laquelle vous ne pouvez utiliser votre base de données pour générer une clé unique, vous devriez voir quelque chose comme un
Guid
- qui a une mucher probabilité plus élevée que la date en temps de manipulation pour générer une valeur unique. Guid peut être trivialement convertis en chaînes de caractères, de sorte que votre identifiant être une chaîne de caractères dans ce cas.Ce que vous faites avec des hachages n'est pas une bonne idée - rien gaurantees que les hachages sera unique - et dans de nombreux cas, ils ne sont en effet entrer en collision. Guid - ne pas fournir une garantie de 100% de l'unicité à travers les machines mais sur une seule machine, ils doivent toujours être unique. Et même à travers les machines, leurs chances de collision sont très éloignées. Aussi, l'utilisation de la machine de temps, comme un moyen de construire la valeur sous-jacente est soumise à des conditions de course (comme ceux que décrit Eric).
Les guid sont de 128 bits des valeurs, de sorte que vous ne pouvez pas représenter comme une simple
int
oulong
. Elle aurait besoin de vous pour utiliser la chaîne comme votre Id, qui peut ou peut ne pas être possible dans votre cas, en fonction d'autres considérations (comme si ou non vous avez le contrôle d'un modèle de données). Si peut utiliser, à l'aide d'un Guid est vraiment facile:Si vraiment vous devez utiliser un identifiant numérique, et vous êtes prêt à abandonner facilement mise à l'échelle de votre application sur plusieurs serveurs, vous pouvez utiliser un auto-incrémenter le nombre global pour la fourniture d'une clé unique. Vous devez graines de ce nombre avec la valeur suivante disponible (max+1) à partir de votre base de données au démarrage de l'application. Vous devez également avoir à les protéger cette valeur à partir de l'utilisation simultanée de plusieurs threads. Je tourne cette responsabilité dans une classe:
EDIT: Dans cette journée et l'âge, des raisons impérieuses pour générer des Identifiants uniques dans votre couche de l'application plutôt qu'à la base de données sont très rares. Vous devriez vraiment utiliser les capacités de la base de données fournit.
OriginalL'auteur LBushkin
Supposons que vous avez deux id de client qui diffèrent par 100, et ils se produisent à la fois de rendre une ordonnance qui est de 100 unités de temps d'intervalle. Votre unicité vient de sortir la fenêtre.
Vous dire que vous allez vérifier la base de données unique; vous ne dites pas ce que vous allez faire si il y a une collision. Vous ne dites pas ce que vous allez faire à propos des conditions de course; supposons que les deux entrent en collision références de commande sont créés à la même époque, ni dans la base de données. Vous demandez à la base de données sur deux threads différents si l'élément est unique; il est. Ensuite, vous entrez à la fois, et le caractère unique a été violé, même si le chèque a été fait.
C'est vraiment un très, très mauvais moyen pour obtenir l'unicité. Ce qui serait mieux, c'est de la déplacer dans la base de données de la couche. Vous pouvez maintenir un mondial, des threads compteur de commandes et d'attribuer à chaque nouvelle commande suivante numéro de commande.
D'ailleurs, depuis de nombreuses années, j'ai demandé une variation sur cette question comme une technique de la question de l'entrevue. J'ai remarqué une forte corrélation entre l'ensemble des personnes qui tentent d'utiliser le temps comme une source de l'unicité et de l'ensemble des personnes qui ne sont pas embauchés. Le temps est un terrible source de l'unicité; beaucoup de différentes choses peuvent se produire en même temps.
Ce qui est encore pire, c'est à l'aide de nombres aléatoires. Les nombres aléatoires sont encore pire source de l'unicité que les horodatages. Supposons que vous disposez d'un véritable générateur de nombre aléatoire qui génère aléatoirement des 32 bits entiers pour Id de commande. Combien de commandes avez-vous besoin d'avoir avant la cote est mieux que cinquante-cinquante-vous que vous avez généré deux commandes avec le même ID? La réponse surprend beaucoup de gens: il n'est que d'environ 77 mille avant il ya une chance de 50% que vous avez généré deux commandes avec le même nombre (et seulement 9300 jusqu'à il y a 1% de chance.)
Rappelez-vous: ce que vous êtes après est un garantie de l'unicité. Pas un probable unicité, mais un fer vêtu de garantir qu'un seul numéro de commande se réfère à une seule commande. Si c'est ce que vous avez besoin, alors assurez-vous de mettre cela en œuvre.
OriginalL'auteur Eric Lippert
Qu'en ayant un champ d'IDENTITÉ dans la base de données le faire pour vous?
Il aura aussi l'avantage supprimé/commande annulée chiffres ne vont pas être réutilisé, ce qui est bon ou peut-être même nécessaires pour la comptabilité).
OriginalL'auteur
SI vous utilisez SQL Server, vous devriez vraiment rechercher l'IDENTITÉ de la spécification. Il vous permet de le faire avec facilité et rapidité.
Votre solution n'est pas unique, car les choses peuvent se produire si rapidement dans le système que les deux processus, soit en cours d'exécution en séquence ou en parallèle, peut obtenir la même valeur de graduation.
OriginalL'auteur Dave Markle
J'aimerais utiliser la colonne d'IDENTITÉ et si ce n'est qu', l'utilisation du Système.Guid.NewGuid() pour générer un GUID pour vous.
OriginalL'auteur itsmatt
Voir Knuth Vol. 2 Chap 3 de Nombres Aléatoires
Vous avez raison, je ne suis pas suggérer un ordre d'ID# être généré de façon aléatoire, seulement que la génération d'un certain nombre de besoins pour être informé des pièges de telles opérations, comme vous l'avez souligné. Aléatoire de la théorie des nombres est un bon endroit pour trouver de tels pièges, de sorte qu'ils peuvent être évités.
OriginalL'auteur Kelly S. French