Je cherche un bon moyen de générer un identifiant de commande unique. Pouvez-vous voir des problèmes avec le code ci-dessous? Je vais vérifier que le numéro est unique dans la base de données avant de créer la commande. P> P>
7 Réponses :
Qu'en est-il d'avoir un champ d'identité dans la base de données le faire pour vous? P>
Il aura également l'avantage que les numéros de commande supprimés / annulés ne soient pas réutilisés (ce qui est bon ou peut être nécessaire pour la comptabilité). P>
Si vous utilisez SQL Server, vous devez vraiment rechercher la spécification d'identité. Cela vous permet de faire cela avec facilité et vitesse. P>
Votre solution n'est pas unique car les choses peuvent se produire si rapidement dans le système que deux processus, fonctionnant dans une séquence ou simultanément, peuvent obtenir la même valeur de tick. p>
L'ID client variera pour chaque commande. Je pense que la combinaison d'une pièce d'identité client avec des tiques devrait produire la valeur unique que je après.
S'il y a une raison impérieuse pour laquelle vous ne pouvez pas utiliser Votre base de données pour générer une clé unique, vous devez consulter quelque chose comme un p> edit: strong> en ce jour et L'âge, des raisons impérieuses de générer des identifiants uniques dans votre couche d'application plutôt que dans la base de données sont très rares. Vous devriez vraiment utiliser les capacités que la base de données fournit. Em> p> p> GUID code>
strong> - qui a une probabilité plus forte plus élevée que la manipulation de date-heure de générer une valeur unique. Les GUID peuvent être trivialement convertis en chaînes. Votre identifiant serait donc une chaîne dans ce cas. P> int code> ou
long code>. Il vous faudrait que vous utilisiez une chaîne comme IDS forte>, qui peut ou non être possible dans votre cas, en fonction des autres considérations (comme si vous contrôlez ou non le modèle de données). Si vous pouvez les utiliser, l'utilisation d'un GUID est vraiment simple: p>
J'utiliserais la colonne d'identité et, sinon, utilisez System.Guid.NewGuid () pour générer un GUID pour vous. P>
Supposons que vous ayez deux identifiants clients qui diffèrent de 100, et ils arrivent à la fois de faire une commande de 100 unités de temps. Votre unicité vient de sortir la fenêtre. P>
Vous dites que vous allez vérifier la base de données pour l'unicité; Vous ne dites pas ce que vous allez faire s'il y a une collision. Vous ne dites pas non plus ce que vous allez faire sur les conditions de course; Supposons que deux identifiants de commande collisionnaires soient créés en même temps, 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. Vous entrez ensuite les deux et l'unicité a été violée même si le chèque a été fait. p>
C'est un moyen vraiment vraiment mauvais d'obtenir un caractère unicité. Ce qui serait mieux consiste à déplacer cela dans la couche de base de données. Vous pouvez maintenir un compteur mondial et threadsafe des commandes et attribuer chaque nouvel ordre le prochain numéro de commande. p>
Incidemment, pendant de nombreuses années, j'ai posé une variation sur cette question en tant que question d'entretien technique. J'ai remarqué une forte corrélation entre l'ensemble de personnes qui tentent d'utiliser du temps comme une source d'unicité et l'ensemble de personnes qui ne sont pas embauchées. Le temps est un source terrible em> de l'unicité; Beaucoup de choses différentes peuvent arriver en même temps. strong> p>
Qu'est-ce qui est encore pire utilise des nombres aléatoires. Les nombres aléatoires sont une source d'unicité encore pire que les horodatages. Supposons que vous ayez un générateur de nombres vraiment aléatoires générant des entiers aléatoires 32 bits pour les identifiants de commande. Combien de commandes avez-vous besoin d'avoir avant que les chances soient meilleures que ce que vous avez généré deux commandes avec le même identifiant? La réponse surprend beaucoup de personnes: il n'ya que 77 000 avant environ 50% de chances que vous avez généré deux commandes avec le même numéro (et seulement 9300 jusqu'à ce qu'il y ait une chance de 1%.) P>
N'oubliez pas: ce que vous êtes après est une garantie em> de l'unicité. Pas un unicité probable em>, mais une garantie de fer à repasser qu'un numéro d'ordre fait référence à une ordonnance exacte. Si c'est ce dont vous avez besoin, assurez-vous de mettre en œuvre cela. P>
Si vous suggérez que l'ID de commande soit généré au hasard en utilisant le véritable aléatoire, il s'agit d'une idée i> dangereuse i>. Les chances d'obtenir une collision entre deux nombres vraiment aléatoires de 32 bits augmentent à> 50% après seulement 77 000 tentatives!
@ERIC: Vous êtes correct, je ne suggère pas d'identifiant de commande # être généré aléatoirement, mais qui générant un certain nombre doit être informé des pièges de telles opérations, comme vous l'avez souligné. La théorie du nombre aléatoire est un bon endroit pour trouver de tels pièges afin qu'ils puissent être évités.
Vous pouvez utiliser une table séparée appelée commande. La table ressemblerait à ceci: p>
[commandercounter] Identifiant CourantCount - Long P>
La table ne contiendra qu'une seule rangée. ID: 1, CourantCount = 1. P>
Lorsque vous souhaitez générer un nouveau numéro de commande, vous accédez à la table à l'aide d'un service, CommandeNumberGenerserVice qui verrouille l'accès à la table, obtenez le numéro actuel, l'incrémentez-la par combien vous voulez. Après incrément, stockez la valeur actuelle dans la table. P>
Donc, par exemple, si vous voulez aller 1 par 1. Var Ordnum = _OrdernumbergenerserVice.GeneratenextOrderNum (); ordnum sera 2 p>
Purement théoriquement, les hachages peuvent entrer en collision.
Ce n'est sûrement pas vraiment unique que vous recherchez, juste le prochain numéro séquentiel ... Je suis d'accord avec le folk ci-dessous en parlant de l'utilisation d'une colonne d'identité.
@Developer Art: Rien de théorique à ce sujet. Hashes collide tout le temps i>. Il n'y a que quatre milliards d'entre eux, bien sûr, ils vont bien sûr entrer en collision.