Comment Créer Déterministe Guid
Dans notre application, nous sommes en créant des fichiers Xml avec un attribut a une valeur Guid. Cette valeur devait être cohérent entre le fichier des mises à niveau. Donc, même si tout le reste dans le fichier change, le guid de la valeur de l'attribut doit rester le même.
Une solution évidente était de créer un dictionnaire statique avec le nom et le Guid à être utilisé pour eux. Alors à chaque fois que nous générer le fichier, nous regardons le dictionnaire pour le nom de fichier et utiliser le guid correspondant. Mais ce n'est pas faisable, parce que nous l'échelle à 100 de fichiers et n'a pas voulu maintenir une grande liste de guid.
Donc une autre approche a été de faire le Guid de la même fonction sur le chemin d'accès du fichier. Depuis que nos chemins d'accès de fichier et de répertoire de l'application à la structure unique, le Guid doit être unique pour ce chemin. Donc, chaque fois qu'une mise à jour, le fichier est le même guid basé sur son chemin. J'en ai trouvé une façon cool pour générer de telles " Déterministe Guid " (Merci Elton Stoneman). Il fait ceci:
private Guid GetDeterministicGuid(string input)
{
//use MD5 hash to get a 16-byte hash of the string:
MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
byte[] inputBytes = Encoding.Default.GetBytes(input);
byte[] hashBytes = provider.ComputeHash(inputBytes);
//generate a guid from the hash:
Guid hashGuid = new Guid(hashBytes);
return hashGuid;
}
Donc, étant donné une chaîne de caractères, le Guid sera toujours le même.
Existe-il d'autres approches ou des recommandations sur les moyens de le faire? Quels sont les avantages ou les inconvénients de cette méthode?
OriginalL'auteur Punit Vora | 2010-04-15
Vous devez vous connecter pour publier un commentaire.
Comme mentionné par @bacar, RFC 4122 §4.3 définit une façon de créer un nom de base de l'UUID. L'avantage de le faire (plus simplement en utilisant un hash MD5) est que ce sont des garanties de ne pas entrer en collision avec les non-nommé-en fonction des Uuid, et ont un très (très) petite possibilité de collision avec un autre nom Uuid.
Il n'y a pas de support natif dans le .NET Framework pour la création de ceux-ci, mais j'ai posté code sur GitHub qui implémente l'algorithme. Il peut être utilisé comme suit:
Pour réduire le risque de collisions avec d'autres Guid encore plus loin, vous pouvez créer un privé GUID pour l'utiliser comme ID d'espace de noms (au lieu d'utiliser l'espace de noms d'URL l'ID défini dans la RFC).
Je n'ai pas d'avis que, grâce/désolé! J'devez toujours vous rappeler de vérifier les errata lors de la lecture d'un RFC... 🙂
Vous êtes les bienvenus/pas de problème. Cela dépasse l'entendement qu'ils n'ont pas de mise à jour de la RFC en place avec les corrections de l'errata. Même un lien à la fin du document serait beaucoup plus utile que de s'appuyer sur le lecteur de se rappeler à la recherche d'errata (j'espère avant écrire une implémentation basée sur la RFC...).
si vous utilisez la version HTML il a un lien pour l'errata de l'en-tête, par exemple tools.ietf.org/html/rfc4122. Je me demande si il y a une extension de navigateur pour toujours rediriger vers la version HTML...
Vous devriez envisager de contribuer à ce .NET .NET résultant de pensions est ici:github.com/dotnet/coreclr/tree/master/src/mscorlib/src/System
OriginalL'auteur Bradley Grainger
Ceci permet de convertir une chaîne en un Guid sans avoir à importer un à l'extérieur de l'assemblée.
Il y a de bien meilleures façons de générer un Guid unique, mais c'est une façon de toujours mise à niveau d'une chaîne de clé de données pour un Guid clé de données.
Avertissement! Ce code ne génère pas valide Guid / Uuid (comme bacar aussi mentionné ci-dessous). Ni la version et le type de champ sont définies correctement.
Ne serait-il pas tout aussi efficace pour utiliser le MD5CryptoServiceProvider au lieu de le SHA1, depuis MD5 est déjà une longueur de 16 octets?
OriginalL'auteur Ben Gripka
De Rob mentionne, votre méthode ne génère pas un UUID, il génère un hash qui ressemble à un UUID.
La RFC 4122 sur Uuid permet spécifiquement déterministe (nom) Uuid - Versions 3 et 5 utilisation de md5 et SHA1(respectivement). La plupart des gens sont familiers avec la version 4, qui est aléatoire. Wikipédia donne une bonne vue d'ensemble des versions. (Notez que l'utilisation du mot "version" ici semble décrire un "type" de l'UUID de la version 5 n'a pas préséance sur la version 4).
Il semble y avoir un peu de bibliothèques pour la génération de la version 3/5 Uuid, y compris la python uuid module, coup de pouce.uuid (C++) et OSSP UUID. (Je n'ai pas regardé pour tout .nette) de
Concernant l'utilisation du mot "version", RFC 4122 §4.1.3 unis: "La version qui est plus exactement un sous-type; encore une fois, nous nous réservons le terme de compatibilité."
J'ai posté un code C# pour créer v3 et v5 Guid sur GitHub: github.com/LogosBible/Logos.Utility/blob/master/src/...
Je reçois Avertissement bit à Bit ou opérateur utilisé sur un signe étendu opérande; envisager un casting pour un plus petit type non signé premier
Cela devient hors-sujet! Vous suggérons de déplacement individuel lib des rapports de bogue sur GitHub.
OriginalL'auteur bacar
MD5 est faible, je crois que vous pouvez faire la même chose avec l'algorithme SHA-1 et d'obtenir de meilleurs résultats.
BTW, juste un avis personnel, dressing un hachage md5 comme un GUID n'en fait pas un bon GUID. Guid par leur nature même, sont non Déterministes. cela se sent comme un tricheur. Pourquoi ne pas appeler un chat un chat et dire ses une chaîne rendu de hachage de l'entrée. vous pouvez le faire en utilisant cette ligne, plutôt que de le nouveau guid ligne:
Ok, appelez votre hash d'un "GUID", le problème est résolu. Ou est le problème réel que vous besoin un
Guid
objet?je voudrais que ce soit si simple.. 🙂 mais oui, j'ai besoin d'un 'GUID' objet
"Guid par leur nature même, sont non Déterministes" - ce n'est vrai que dans certains types (les "versions") de Guid. Cependant je suis d'accord que "dressing un hachage md5 comme un GUID ne fait pas un bon GUID" pour d'autres raisons, comme indiqué par @Bradley Grainger et @Rob Fonseca Ensor, et ma réponse à cette question.
OriginalL'auteur ryber
Vous avez besoin de faire une distinction entre les instances de la classe
Guid
, et identifiants qui lui sont uniques au monde. Un "déterministe" guid " est en fait une table de hachage (comme en témoigne votre appel àprovider.ComputeHash
). Hachages ont beaucoup plus de chances de collisions (deux chaînes qui arrive à produire le même hash) que Guid créé parGuid.NewGuid
.Donc le problème avec votre approche est qu'il vous faudra être ok avec la possibilité que les deux chemins différents produira le même GUID. Si vous avez besoin d'un identifiant unique pour chaque chaîne de chemin, alors la meilleure chose à faire est de suffit d'utiliser la chaîne. Si vous avez besoin de la chaîne à être cachées à partir de vos utilisateurs, chiffrer - vous pouvez utiliser ROT13 ou quelque chose de plus puissant...
De la tentative d'incorporer quelque chose qui n'est pas un pur GUID dans le GUID type de données pourrait conduire à des problèmes de maintenance dans le futur...
OriginalL'auteur Rob Fonseca-Ensor