Chinees - Simplificeren   Duits   Engels (Verenigde Staten)   Frans   Nederlands   Portugees - Iberisch   Spaans  

Home




Usenet Posting #11 - Trigeminal Software, Inc. (Dutch)


Onderwerp: INFO: Replicatie en GUIDs, de Goede, de Slechte en de Lelijke
(Oorspronkelijk gepost 26 juli 1999)
Globally Unique Identifiers... of GUIDs (uitgesproken als Geoduck met "uck" of als "Goe-id" voor mensen die het andere niet kunnen zeggen) zijn in principe uniek in tijd en ruimte. Ze worden gebruikt in COM en ze worden gebruikt in Jet-replicatie om een ID te creeren voor records die constant en uniek blijven ongeacht welke andere waarden (zoals sleutelwaarden) veranderen.

Veel mensen overwegen het idee om GUIDs te gebruiken voor hun primaire/referentiele sleutel, omdat ze uniciteit garanderen. Er zijn echter veel redenen om hier nog even bij stil te staan:

1) Als je in een applicatie een "ReplicatieID Autonummering-veld" (dwz een autonummering-GUID) gebruikt, die vervolgens tot replica wordt gemaakt, zal Jet jouw kolom gebruiken in plaats van een s_Guid-kolom te genereren. Helaas nemen de Conflict Resolver-wizard van Access 96 en 97 en de Conflict Viewer van Access 2000 aan dat er een s_Guid-kolom is. Conflictoplossing zal dus niet goed werken via de wizard, en je moet het zelf uitzoeken.

2) Een GUID wordt letterlijk opgeslagen als een 16-byte binaire waarde. Het heeft ook een canonieke (tekst-) vorm en een DAO/Jet-vorm, bestaande uit {guid {xxx}}, waar xxx de "canonieke" waarde is. Dit laatste formaat zal Jet altijd laten zien als je een select-statement uitvoert van een GUID-veld via DAO... de canonieke vorm wordt gebruikt als je direct via Jet gaat (als in Access-gegevensbladen) of ADO via de Jet OLE DB provider. Daarbij zijn de regels van DAO- versus ADO-filters, zoekopdrachten, Access-Domeinfuncties, Access-formulierfilters, links tussen formulier en subformulier, .Text versus .Value voor controls die zijn verbonden aan GUID-velden en alle zoekmethoden moeilijk te volgen en ze veranderen bij elke versie. Access heeft ingebouwde functies om de conversie tussen binaire en canonieke vorm te ondersteunen, namelijk StringFromGUID en GUIDFromString, maar zij gebruiken helaas de DAO-syntax, hoewel alles van COM en de meeste andere bronnen de voorkeur geven aan rechttoe rechtaan canoniek. Deze hele mengelmoes betekent dat het gebruiken van een GUID-veld voor deze operaties is als schieten op een bewegend doel.

3) De regels in #2 veranderen met elke versie en wijken bijna altijd af van de vorige versie. Daarom moet je in wezen al je werk opnieuw herzien bij elke upgrade.

4) Autonummers zijn vaak zichtbaar voor gebruikers, in voor- en tegenspoed. Dit is natuurlijk heel onpraktisch voor GUIDs, zelfs als het scala van minpunten met zoeken en zo geen echte problemen waren. GUIDs brengen gebruikers alleen maar in verwarring en niemand wil dat een GUID zich bekend maakt. :-)

Het is waar dat alle zaken die in #2 worden aangeduid, via verschillende technieken kunnen worden afgehandeld, waaronder:

1) Experimenteren met het gebruik van de echte canonieke vorm versus de {guid{xxx}}-canonieke vorm

2) Conversie via de twee Access-functies

3) CStr() gebruiken in de waarden van de velden in het SELECT-statement die GUIDs teruggeven zodat je het echte canonieke formaat krijgt

4) Alle plaatsen waar je iets wijzigt noteren, zodat je ze als/wanneer je upgrade weer kunt opzoeken (omdat de meeste in de volgende versie veranderd zullen zijn).

Je realiseren dat het onderliggende veld in het geval van DAO een dbGuid-type veld is en in het geval van ADO een adGuid-type... hoewel beide een veld van het type "tekst" teruggeven als je alleen maar kijkt naar de waarde. Dit toont nog maar eens aan hoe veel moeite ze allemaal doen om flexibel te lijken... dit is de belangrijkste reden waarom de zaken in #2 zo moeilijk te voorspellen zijn.

Hier zijn trouwens de niet-Access-functies om Guid/String en String/Guid-zaken uit te voeren als je werkt vanuit VB. Plak het in een module enzovoort.

Type GUID 
    Data1 As Long 
    Data2 As Integer 
    Data3 As Integer 
    Data4(7) As Byte 
End Type 

Private Declare Function _ 
 StringFromGUID2 Lib "ole32.dll" _ 
 (rclsid As GUID, ByVal lpsz As Long, _ 
 ByVal cbMax As Long) As Long 

Private Declare Function _ 
 CLSIDFromString Lib "ole32.dll" _ 
 (pstCLS As Long, clsid As GUID) As Long 

Function GuidFromStGuid(stGuid As String) As GUID 
    Call CLSIDFromString(ByVal StrPtr(stGuid), _ 
     GuidFromStGuid) 
End Function 

Function StGuidFromGuid(rclsid As GUID) As String 
    Dim stGuid As String 
    Dim cch As Long 

    ' 39 tekens voor de GUID plus ruimte voor het Null-teken
    stGuid = String$(40, vbNullChar) 
    cch = StringFromGUID2(rclsid, StrPtr(stGuid), 39) 
    StGuidFromGuid = Left$(stGuid, cch) 
End Function 

LAATSTE AANBEVELING:

Het is wel mogelijk om de zaken in #2 en #3 te overkomen, maar #2 is zeer problematisch en heel moeilijk onderhoudbaar in het licht van #3. Het is in het algemeen de risico's van bugs en geforceerde upgrade-problemen niet waard. Er zijn betere manieren om primaire sleutels te kiezen die dergelijke problemen niet met zich mee brengen... dus het is bijna altijd aan te raden om die manieren te kiezen als je schone en makkelijk onderhoudbare database- en gerepliceerde applicaties wilt schrijven.

MichKa
ReplicaID: {E5D50A9B-33D2-11D3-AAB3-00104BA31425}

Back to Usenet Musings


Problemen met deze pagina? Neem contact op met de webmaster@trigeminal.com
met uw commentaar, vragen of suggesties.