home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Tool Box
/
SIMS_2.iso
/
demo
/
rec_lock
/
rec_lock.txt
< prev
next >
Wrap
Text File
|
1994-09-09
|
25KB
|
464 lines
Record Locking Pro Demo - Dokumentation
=======================================
1. Systemvoraussetzungen
------------------------
IBM-kompatibler PC mit 386-Prozessor
mindestens 4 MB Hauptspeicher
mindestens 5 MB Festplattenspeicher
Microsoft Windows 3.1 oder h÷her
Microsoft Visual Basic 3.0 bzw. Microsoft Access 1.1 oder 2.0
2. Allgemeines
--------------
Record Locking Pro ist ein Programmiertool, welches Ihnen die Realisierung
einer echten Datensatzsperrung unter Microsoft Visual Basic 3.0 wie auch
Microsoft Access 2.0 erm÷glicht. Zum Software-Paket geh÷ren: eine DLL-
Bibliothek namens REC_LOCK.DLL, die interne Funktionen zur Verwaltung von
Datensatzsperrungen enthΣlt, ein Basic-Modul namens GLOBALS.BAS, welches
Routinen des Record-Locking-Systems in reinem Visual Basic zur Verfⁿgung
stellt, zwei Beispielprogramme und diese Dokumentation.
Die Demo-Version ist auf maximal 2 User, 2 Datenbank-Tabellen bzw. Abfra-
gen und 100 DatensΣtze pro Tabelle/Abfrage beschrΣnkt.
Wichtig!
In Ihren Visual-Basic bzw. Access-Programmen sollten Sie nicht direkt die
Funktionen der DLL-Bibliothek, sondern die Routinen des eben erwΣhnten
Basic-Moduls benutzen, da diese viel einfachere Aufrufkonventionen haben
als die DLL-Routinen. Darⁿber hinaus sind die Routinen aus dem Modul GLO-
BALS.BAS wesentlich kompakter und komfortabler.
Wie Sie wissen, kennt die Access-Engine in den Versionen 1.1 und 2.0 nur
die sogenannte Seitensperrung (Page Locking), bei der gleich mehrere Da-
tensΣtze beim Zugriff auf einen bestimmten Datensatz gesperrt werden. Re-
cord Locking Pro bietet hier Abhilfe, ist jedoch nicht fⁿr den Einsatz in
sehr gro▀en Datenbanksystemen gedacht, da die Datensatzsperrung extern mit
Umgehung der Access-Engine funktioniert, weshalb auch gewisse Grenzen be-
zⁿglich der zu verwaltenden User, Tabellen und DatensΣtze gesetzt werden
mu▀ten (dazu gleich mehr). Die Sperrvermerke werden in einer separaten Re-
cord-Locking-Verwaltungsdatei gespeichert. Diese wird, sofern nicht vor-
handen, von der Initialisierungsroutine erzeugt.
Insgesamt k÷nnen mit der Vollversion 1.01 des vorliegenden Tools bis zu 50
User in einer Mehrbenutzer-Umgebung, weiterhin bis zu 100 Datenbank-Tabel-
len bzw. Abfragen und bis zu 500 Datensatzsperrungen pro Tabelle/Abfrage in
einer Datei verwaltet werden. Die Record-Locking-Verwaltungsdatei hat die
Gr÷▀e von etwa 700 KB (Vollversion). Es k÷nnen mehrere solche Dateien mit
unterschiedlichen Namen vom Programmierer erzeugt und verwaltet werden.
Mit Record Locking Pro kann fⁿr jeden zu sperrenden Datensatz eine soge-
nannte automatische Entsperrⁿberwachung eingestellt werden. Dazu wird ein
Lock-Timeout, eine Zeitmarke in Sekunden gesetzt, deren ▄berschreitung vom
Programmierer abgefragt werden kann, so da▀ ggf. der entsprechende Daten-
satz entsperrt werden kann. Auf diese Weise lΣ▀t sich leicht die Sperrung
eines Datensatzes ⁿberwachen.
Fⁿr jeden gesperrten Datensatz lassen sich eine Reihe zusΣtzlicher Infor-
mationen abfragen. Dazu geh÷ren in erster Linie das Sperrdatum und die
Sperrzeit. Darⁿber hinaus kann auch die Zeit in Sekunden seit der Sperrung
abgefragt werden. Auch der Benutzer, den einen bestimmten Datensatz ge-
sperrt hat, lΣ▀t sich auf einfache Weise ermitteln.
GrundsΣtzlich kann man pro User zwischen zwei verschiedenen Sperrmethoden
wΣhlen, deren Verwaltung jedoch manuell in einem VB-Programm programmiert
werden mu▀, da Visual Basic 3.0 standardmΣ▀ig keine Callback-Funktionen zur
Verfⁿgung stellt, mit deren Hilfe man die Sperrungen steuern k÷nnte:
Lock-by-Select (Datensatzsperrung bei Selektion) und Lock-by-Edit (Daten-
satzsperrung erst bei Beginn des Editiervorgangs). Bitte beachten Sie, da▀
die Record-Locking-Verwaltungsdatei nur reine Informationen ⁿber die ein-
gestellte Sperrmethode speichert.
Was Record Locking Pro im einzelnen noch alles kann, entnehmen Sie bitte
der Dokumentation der Routinen aus dem Modul GLOBALS.BAS.
3. Was mu▀ bei der Programmierung beachtet werden?
--------------------------------------------------
In jedes Visual-Basic-Projekt, in welchem Record Locking Pro eingesetzt
wird, mu▀ die Datei GLOBALS.BAS mit der Implementation der einzelnen Rou-
tinen fⁿr die Verwaltung der Datensatzsperrungen eingebunden werden. Dann
k÷nnen in jedem weiteren Modul und jeder weiteren Form eines VB-Projektes
diese Routinen aufgerufen werden. Die direkte Benutzung der DLL-Funktionen
ist - wie am Anfang des Abschnitts "Allgemeines" schon gesagt - nicht emp-
fehlenswert.
Um Record Locking Pro erfolgreich einzusetzen, mu▀ man einige Konventionen
beachten. Das Allerwichtigste ist, da▀ jeder zu sperrende Datensatz ein-
deutig identifizierbar sein mu▀ und zwar durch einen Wert vom VB-Typ Long.
Dieser Wert wird bei der Entsperrung des betreffenden Datensatzes ben÷tigt,
wie auch bei der Abfrage verschiedener Informationen ⁿber einen Datensatz.
Au▀er der Datensatz-ID mu▀ bei jeder Sperrung bzw. Entsperrung der Name der
Datenbank-Tabelle bzw. Abfrage, in der sich der betreffende Datensatz be-
findet, ⁿbergeben werden. Der Name des Benutzers braucht man nur bei der
Initialisierung des Record-Locking-Systems zu ⁿbergeben. Das System spei-
chert den Namen in einer globalen Varia-blen und benutzt ihn bei Aufruf
aller anderen Routinen, die Record Locking Pro zur Verfⁿgung stellt (Modul
GLOBALS.BAS).
Bei Abfragen mu▀ man besondere Konventionen bei der Sperrung einzelner Da-
tensΣtze beachten. Am besten ist es, wenn die einzelnen DatensΣtze aller
zu einer Abfrage geh÷renden Datenbank-Tabellen gesperrt werden. Damit wird
gewΣhrleistet, da▀ kein anderer Benutzer mehr au▀er dem, der die Sperrung
vornimmt, diese DatensΣtze editieren kann, solange sie nicht wieder frei-
gegeben werden. Bitte beachten Sie, da▀ auch hier jeder Datensatz eindeutig
identifizierbar sein mu▀.
4. Record-Locking-Routinen und sonstige Deklarationen
-----------------------------------------------------
Im folgenden finden Sie die Deklarationen der Record-Locking-Routinen
sowie die Deklarationen der globalen Variablen und Konstanten (Modul
GLOBALS.BAS).
' Status-Konstanten
Global Const st_No_Error = 0 ' kein Fehler
Global Const st_Record_Not_Locked = 0 ' Datensatz ist nicht gesperrt
Global Const st_DOS_Error = 1 ' DOS-Fehler (Details -> globale
Variable glb_Last_DOS_Error)
Global Const st_No_File_Name = 2 ' Name der Record-Locking-
Verwaltungsdatei fehlt
Global Const st_No_User_Name = 3 ' Username fehlt
Global Const st_Max_Users = 4 ' max. Anzahl User erreicht
Global Const st_File_Destroyed = 5 ' Record-Locking-Verwaltungsdatei
ist zerst÷rt
Global Const st_User_Not_Found = 6 ' User nicht gefunden
Global Const st_No_Table_Name = 7 ' Name der Datenbank-Tabelle bzw.
Abfrage fehlt
Global Const st_Max_Tables = 8 ' max. Anzahl Tabellen erreicht
Global Const st_Lock_By_Same = 9 ' Datensatz vom akt. Benutzer ge-
sperrt; keine automatische
Entsperrⁿberwachung oder Zeitmarke
noch nicht ⁿberschritten
Global Const st_Lock_By_Others = 10 ' Datensatz von einem anderem User
gesperrt; keine automatische
Entsperrⁿberwachung oder Zeitmarke
noch nicht ⁿberschritten
Global Const st_Lock_By_Same_Out = 11 ' Datensatz vom akt. Benutzer ge-
sperrt; Zeitmarke fⁿr die Sperrung
ⁿberschritten, Entsperrung wird
empfohlen
Global Const st_Lock_By_Others_Out = 12 ' Datensatz von einem anderem User
gesperrt; Zeitmarke fⁿr die Sper-
rung ⁿberschritten, Entsperrung
wird empfohlen
Global Const st_Max_Records = 13 ' max. Anzahl sperrbarer DatensΣtze
erreicht
Global Const st_Table_Not_Found = 14 ' Datenbank-Tabelle bzw. Abfrage
nicht gefunden
Global Const st_Record_Not_Found = 15 ' Datensatz nicht gefunden
' Sperrmethoden-Konstanten
Global Const lock_by_Select = 0 ' Lock-by-Select (Sperren bei Datensatz-
Selektion)
Global Const lock_by_Edit = 1 ' Lock-by-Edit (Sperren bei Beginn des Edi-
tiervorgangs eines Datensatzes)
' Globale Variablen
Global glb_Last_Status As Integer ' letzter Status eines DLL-
Funktionsaufrufes
Global glb_Last_DOS_Error As Integer ' Code des letzten DOS-Fehlers
Global glb_Lock_File_Name As String ' Name der Record-Locking-
Verwaltungsdatei inkl. Pfad
Global glb_User_Name As String ' Name des akt. Benutzers
Global glb_Lock_Mode As Integer ' Sperrmethode
'============================================================
' Routine : Clear_Table
'============================================================
' Aufgabe : L÷scht einen Tabellen/Abfragen-Eintrag aus der Re-
' cord-Locking-Verwaltungsdatei inkl. aller zugeh÷ri-
' gen gesperrten DatensΣtze
' Eingabe : Table_Name = Name der Datenbank-Tabelle bzw. Abfrage
' (max. 40 Zeichen)
' Ausgabe : keine
' Info : Fⁿr den internen Aufruf der entsprechenden DLL-Funk-
' tion wird die globale Variable glb_Lock_File_Name
' benutzt.
' Status und evtl. DOS-Fehler k÷nnen ⁿber die globalen
' Variablen glb_Last_Status und glb_Last_DOS_Error
' abgefragt werden.
'------------------------------------------------------------
Sub Clear_Table (Table_Name As String)
'============================================================
' Routine : Done_Locking
'============================================================
' Aufgabe : Beendet das Record-Locking-System. Alle vom akt.
' Benutzer gesperrten DatensΣtze werden entsperrt.
' Eingabe : keine
' Ausgabe : keine
' Info : Fⁿr den internen Aufruf der entsprechenden DLL-Funk-
' tion werden die globalen Variablen glb_Lock_File_Name
' und glb_User_Name benutzt.
' Status und evtl. DOS-Fehler k÷nnen ⁿber die globalen
' Variablen glb_Last_Status und glb_Last_DOS_Error
' abgefragt werden.
'------------------------------------------------------------
Sub Done_Locking ()
'============================================================
' Routine : Get_Lock_Date
'============================================================
' Aufgabe : Liefert das Sperrdatum eines Datensatzes in Form
' eines formatierten Strings zurⁿck, falls der Daten-
' satz gesperrt ist. Ist der Datensatz nicht gesperrt
' oder ein Fehler aufgetreten, so wird ein leerer
' String zurⁿckgeliefert.
' Eingabe : Table_Name = Name der Datenbank-Tabelle bzw. Abfrage
' (max. 40 Zeichen)
' Record_ID = Datensatz-ID (mu▀ >= 0 sein)
' Ausgabe : keine
' Return : Sperrdatum; Format: "DD.MM.YYYY" bzw. leerer String
' Info : Eine Sperrung liegt auch vor, wenn die evtl. ein-
' gestellte Zeitmarke (Lock-Timeout) fⁿr die automa-
' tische Entsperrⁿberwachung bereits ⁿberschritten
' ist. Dies jedoch kann mit Hilfe der Funktion
' Is_Record_Locked abgefragt werden.
'------------------------------------------------------------
Function Get_Lock_Date (Table_Name As String, Record_ID As Long) As String
'============================================================
' Routine : Get_Lock_Mode
'============================================================
' Aufgabe : Liefert das Sperrmethode, die fⁿr den akt. Benutzer
' gilt. Ist ein Fehler aufgetreten, so wird der Wert
' -1 zurⁿckgeliefert.
' Eingabe : keine
' Ausgabe : keine
' Return : Sperrmethode: 0 = Lock-by-Select (Sperren bei Daten-
' satz-Selektion)
' 1 = Lock-by-Edit (Sperren bei Beginn des
' Editiervorgangs eines Datensatzes)
'------------------------------------------------------------
Function Get_Lock_Mode () As Integer
'============================================================
' Routine : Get_Lock_Seconds
'============================================================
' Aufgabe : Liefert die Sperrzeit fⁿr einen gesperrten Datensatz
' in Sekunden (wird ab dem Zeitpunkt der Sperrung ge-
' rechnet). Ist der Datensatz nicht gesperrt oder
' Fehler aufgetreten, so wird der Wert 0 zurⁿckgelie-
' fert.
' Eingabe : Table_Name = Name der Datenbank-Tabelle bzw. Abfrage
' (max. 40 Zeichen)
' Record_ID = Datensatz-ID (mu▀ >= 0 sein)
' Ausgabe : keine
' Return : Sperrzeit in Sekunden
'------------------------------------------------------------
Function Get_Lock_Seconds (Table_Name As String, Record_ID As Long) As Long
'============================================================
' Routine : Get_Lock_Time
'============================================================
' Aufgabe : Liefert die Sperrzeit eines Datensatzes in Form
' eines formatierten Strings zurⁿck, falls der Daten-
' satz gesperrt ist. Ist der Datensatz nicht gesperrt
' oder ein Fehler aufgetreten, so wird ein leerer
' String zurⁿckgeliefert.
' Eingabe : Table_Name = Name der Datenbank-Tabelle bzw. Abfrage
' (max. 40 Zeichen)
' Record_ID = Datensatz-ID (mu▀ >= 0 sein)
' Ausgabe : keine
' Return : Sperrzeit; Format: "HH:MM:SS" bzw. leerer String
' Info : Eine Sperrung liegt auch vor, wenn die evtl. ein-
' gestellte Zeitmarke (Lock-Timeout) fⁿr die automa-
' tische Entsperrⁿberwachung bereits ⁿberschritten
' ist. Dies jedoch kann mit Hilfe der Funktion
' Is_Record_Locked abgefragt werden.
'------------------------------------------------------------
Function Get_Lock_Time (Table_Name As String, Record_ID As Long) As String
'============================================================
' Routine : Get_Lock_Timeout
'============================================================
' Aufgabe : Liefert die fⁿr einen gesperrten Datensatz einge-
' stellte Zeitmarke fⁿr die automatische Entsperrⁿber-
' wachung zurⁿck. Der Wert 0 bedeutet keine automati-
' sche Entsperrⁿberwachung. Ist der Datensatz nicht
' gesperrt oder Fehler aufgetreten, so wird der Wert
' -1 zurⁿckgeliefert.
' Eingabe : Table_Name = Name der Datenbank-Tabelle bzw. Abfrage
' (max. 40 Zeichen)
' Record_ID = Datensatz-ID (mu▀ >= 0 sein)
' Ausgabe : keine
' Return : Lock-Timeout in Sekunden
'------------------------------------------------------------
Function Get_Lock_Timeout (Table_Name As String, Record_ID As Long) As Integer
'============================================================
' Routine : Get_Lock_User
'============================================================
' Aufgabe : Liefert den Namen des Benutzers zurⁿck, der den an-
' gegebenen Datensatz gesperrt hat. Ist der Datensatz
' nicht gesperrt oder ein Fehler aufgetreten, so wird
' ein leerer String zurⁿckgeliefert.
' Eingabe : Table_Name = Name der Datenbank-Tabelle bzw. Abfrage
' (max. 40 Zeichen)
' Record_ID = Datensatz-ID (mu▀ >= 0 sein)
' Ausgabe : keine
' Return : Benutzername (String) bzw. leerer String
' Info : Eine Sperrung liegt auch vor, wenn die evtl. ein-
' gestellte Zeitmarke (Lock-Timeout) fⁿr die automa-
' tische Entsperrⁿberwachung bereits ⁿberschritten
' ist. Dies jedoch kann mit Hilfe der Funktion
' Is_Record_Locked abgefragt werden.
' Status und evtl. DOS-Fehler k÷nnen ⁿber die globalen
' Variablen glb_Last_Status und glb_Last_DOS_Error
' abgefragt werden.
'------------------------------------------------------------
Function Get_Lock_User (Table_Name As String, Record_ID As Long) As String
'============================================================
' Routine : Get_Login_Date
'============================================================
' Aufgabe : Liefert das Login-Datum des akt. Benutzers in Form
' eines formatierten Strings. Ist der Benutzer nicht
' im System eingeloggt oder ist ein Fehler aufgetreten,
' so wird ein leerer String zurⁿckgeliefert.
' Eingabe : keine
' Ausgabe : keine
' Return : Login-Datum; Format: "DD.MM.YYYY" bzw. leerer String
'------------------------------------------------------------
Function Get_Login_Date () As String
'============================================================
' Routine : Get_Login_Seconds
'============================================================
' Aufgabe : Liefert die Login-Zeit des akt. Benutzers in Sekun-
' den. Ist der Benutzer nicht im System eingeloggt
' oder ist ein Fehler aufgetreten, so wird 0 zurⁿck-
' geliefert.
' Eingabe : keine
' Ausgabe : keine
' Return : Login-Zeit in Sekunden
' Info : Status und evtl. DOS-Fehler k÷nnen ⁿber die globalen
' Variablen glb_Last_Status und glb_Last_DOS_Error
' abgefragt werden.
'------------------------------------------------------------
Function Get_Login_Seconds () As Long
'============================================================
' Routine : Get_Login_Time
'============================================================
' Aufgabe : Liefert die Login-Zeit des akt. Benutzers in Form
' eines formatierten Strings. Ist der Benutzer nicht
' im System eingeloggt oder ist ein Fehler aufgetreten,
' so wird ein leerer String zurⁿckgeliefert.
' Eingabe : keine
' Ausgabe : keine
' Return : Login-Zeit; Format: "HH:MM:SS" bzw. leerer String
'------------------------------------------------------------
Function Get_Login_Time () As String
'============================================================
' Routine : Init_Locking
'============================================================
' Aufgabe : Initialisiert das Record-Locking-System.
' Eingabe : File_Name = Name der Record-Locking-Verwaltungsdatei
' User_Name = Benutzername (max. 20 Zeichen)
' Lock_Mode = Sperrmethode: 0 = Lock-by-Select (Sper-
' ren bei Datensatz-Se-
' lektion)
' 1 = Lock-by-Edit (Sperren
' bei Beginn des Editier-
' vorgangs eines Daten-
' satzes)
' Ausgabe : keine
' Info : File_Name, User_Name und Lock_Mode werden nach Auf-
' ruf dieser Routine in entsprechenden globalen Va-
' riablen gespeichert, die dann in anderen Routinen
' benutzt werden. Auf diese Weise bleiben dem Prog-
' rammierer Eingabeparameter erspart.
' Status und evtl. DOS-Fehler k÷nnen ⁿber die globalen
' Variablen glb_Last_Status und glb_Last_DOS_Error
' abgefragt werden.
'------------------------------------------------------------
Sub Init_Locking (File_Name As String, User_Name As String, Lock_Mode As Integer)
'============================================================
' Routine : Is_Record_Locked
'============================================================
' Aufgabe : Liefert st_Record_Not_Locked zurⁿck, wenn der an-
' gegebene Datensatz nicht gesperrt ist. Ist der Da-
' tensatz gesperrt, so wird einer der folgenden Wer-
' te zurⁿckgeliefert:
' st_Lock_By_Same, st_Lock_By_Others,
' st_Lock_By_Same_Out, st_Lock_By_Others_Out
' Die Bedeutung der Konstanten ist im Deklarations-
' teil dieses Moduls erlΣutert.
' Tritt ein Fehler auf, so wird der entsprechende
' Fehlerstatus in der Variablen glb_Last_Status
' gespeichert. Handelt es sich sogar um einen DOS-
' Fehler, so wird dessen Code in der globalen Va-
' riablen glb_Last_DOS_Error vermerkt.
' Eingabe : Table_Name = Name der Datenbank-Tabelle bzw. Abfrage
' (max. 40 Zeichen)
' Record_ID = Datensatz-ID (mu▀ >= 0 sein)
' Ausgabe : keine
' Return : Status (wie oben beschrieben)
'------------------------------------------------------------
Function Is_Record_Locked (Table_Name As String, Record_ID As Long) As Integer
'============================================================
' Routine : Is_Record_Locked_Gen
'============================================================
' Aufgabe : Prⁿft, ob ein Datensatz generell gesperrt ist, d.h.
' unabhΣngig davon, welcher Benutzer ihn gesperrt
' hat und ob die Zeitmarke fⁿr die evtl. eingestell-
' te Entsperrⁿberwachung bereits ⁿberschritten ist
' oder nicht. Es wird True bzw. False (Datensatz nicht
' gesperrt) zurⁿckgeliefert.
' Eingabe : Table_Name = Name der Datenbank-Tabelle bzw. Abfrage
' (max. 40 Zeichen)
' Record_ID = Datensatz-ID (mu▀ >= 0 sein)
' Ausgabe : keine
' Return : True bzw. False
'------------------------------------------------------------
Function Is_Record_Locked_Gen (Table_Name As String, Record_ID As Long) As Integer
'============================================================
' Routine : Lock_Record
'============================================================
' Aufgabe : Sperrt einen Datensatz in einer Datenbank-Tabelle
' bzw. Abfrage. Ist der zu sperrende Datensatz bereits
' gesperrt und ist fⁿr den Datensatz eine automati-
' sche Entsperrⁿberwachung eingeschaltet, so wird ge-
' prⁿft, ob die eingestellte Zeitmarke ⁿberschritten
' ist; ggf. wird in der Variablen glb_Last_Status ver-
' merkt, da▀ der Datensatz zu entsperren ist
' (st_Lock_By_Same_Out, st_Lock_By_Others_Out). Ist
' der Datensatz gesperrt und entweder keine Entsperr-
' ⁿberwachung eingestellt oder die Zeitmarke noch
' nicht ⁿberschritten, so hat die Variable glb_Last_Status
' den Wert st_Lock_By_Same bzw. st_Lock_By_Others.
' Eingabe : Table_Name = Name der Datenbank-Tabelle bzw. Abfrage
' (max. 40 Zeichen)
' Record_ID = Datensatz_ID (mu▀ >= 0 sein)
' Timeout = Zeitvorgabe fⁿr die automatische Ent-
' sperrⁿberwachung (in Sekunden; 0 bedeu-
' tet keine automatische Entsperrⁿberwa-
' chung)
' Ausgabe : keine
'------------------------------------------------------------
Sub Lock_Record (Table_Name As String, Record_ID As Long, Timeout As Integer)
'============================================================
' Routine : Unlock_Record
'============================================================
' Aufgabe : Entsperrt den angegebenen Datensatz unabhΣngig da-
' von, welcher Benutzer ihn gesperrt hat.
' Eingabe : Table_Name = Name der Datenbank-Tabelle bzw. Abfrage
' (max. 40 Zeichen)
' Record_ID = Datensatz-ID (mu▀ >= 0 sein)
' Ausgabe : keine
' Info : Fⁿr den internen Aufruf der entsprechenden DLL-Funk-
' tion wird die globale Variable glb_Lock_File_Name
' benutzt.
' Status und evtl. DOS-Fehler k÷nnen ⁿber die globalen
' Variablen glb_Last_Status und glb_Last_DOS_Error
' abgefragt werden.
'------------------------------------------------------------
Sub Unlock_Record (Table_Name As String, Record_ID As Long)