Dela via


TN053: Anpassade DFX-rutiner för DAO-databasklasser

Anmärkning

DAO används med Access-databaser och stöds via Office 2013. DAO 3.6 är den slutliga versionen och anses vara föråldrad. Visual C++-miljön och guiderna stöder inte DAO (även om DAO-klasserna ingår och du fortfarande kan använda dem). Microsoft rekommenderar att du använder OLE DB-mallar eller ODBC och MFC för nya projekt. Du bör bara använda DAO för att underhålla befintliga program.

Den här tekniska anmärkningen beskriver mekanismen för DAO-postfältutbyte (DFX). För att förstå vad som händer i DFX-rutinerna DFX_Text förklaras funktionen i detalj som ett exempel. Som ytterligare informationskälla till den här tekniska anmärkningen kan du undersöka koden för de andra enskilda DFX-funktionerna. Du behöver förmodligen inte en anpassad DFX-rutin så ofta som du kanske behöver en anpassad RFX-rutin (används med ODBC-databasklasser).

Den här tekniska anmärkningen innehåller:

Översikt över DFX

DAO-postfältutbytesmekanismen (DFX) används för att förenkla proceduren för att hämta och uppdatera data när du använder CDaoRecordset klassen. Processen förenklas med hjälp av datamedlemmar i CDaoRecordset klassen. Genom att härleda från CDaoRecordsetkan du lägga till datamedlemmar i den härledda klassen som representerar varje fält i en tabell eller fråga. Den här "statiska bindningsmekanismen" är enkel, men det kanske inte är den datahämtnings-/uppdateringsmetod som du väljer för alla program. DFX hämtar varje bundet fält varje gång den aktuella posten ändras. Om du utvecklar ett prestandakänsligt program som inte kräver att alla fält hämtas när valutan ändras, "dynamisk bindning" via CDaoRecordset::GetFieldValue och CDaoRecordset::SetFieldValue kan vara valfri dataåtkomstmetod.

Anmärkning

DFX och dynamisk bindning är inte ömsesidigt uteslutande, så en hybridanvändning av statisk och dynamisk bindning kan användas.

Exempel 1 – Endast användning av DAO Record Field Exchange

(förutsätter CDaoRecordset – den härledda klassen CMySet är redan öppen)

// Add a new record to the customers table
myset.AddNew();

myset.m_strCustID = _T("MSFT");

myset.m_strCustName = _T("Microsoft");

myset.Update();

Exempel 2 – Endast användning av dynamisk bindning

(förutsätter att du använder CDaoRecordset klassen , rsoch att den redan är öppen)

// Add a new record to the customers table
COleVariant  varFieldValue1 (_T("MSFT"),
    VT_BSTRT);

//Note: VT_BSTRT flags string type as ANSI,
    instead of UNICODE default
COleVariant  varFieldValue2  (_T("Microsoft"),
    VT_BSTRT);

rs.AddNew();

rs.SetFieldValue(_T("Customer_ID"),
    varFieldValue1);

rs.SetFieldValue(_T("Customer_Name"),
    varFieldValue2);

rs.Update();

Exempel 3 – Användning av DAO Record Field Exchange och dynamisk bindning

(förutsätter att du bläddrar bland anställdas data med CDaoRecordset-härledd klass emp)

// Get the employee's data so that it can be displayed
emp.MoveNext();

// If user wants to see employee's photograph,
// fetch it
COleVariant varPhoto;
if (bSeePicture)
    emp.GetFieldValue(_T("photo"),
    varPhoto);

// Display the data
PopUpEmployeeData(emp.m_strFirstName,
    emp.m_strLastName,
    varPhoto);

Så här fungerar DFX

DFX-mekanismen fungerar på ett liknande sätt som rfx-mekanismen (record field exchange) som används av MFC ODBC-klasserna. Principerna för DFX och RFX är desamma, men det finns många interna skillnader. Utformningen av DFX-funktionerna var sådan att praktiskt taget all kod delas av de enskilda DFX-rutinerna. På den högsta nivån gör DFX bara ett fåtal saker.

  • DFX konstruerar SQL SELECT-satsen och SQL PARAMETERS-satsen om det behövs.

  • DFX konstruerar bindningsstrukturen som används av DAO:s GetRows funktion (mer om detta senare).

  • DFX hanterar databufferten som används för att identifiera felaktiga fält (om dubbelbuffertning används)

  • DFX hanterar null - och DIRTY-statusmatriserna och anger värden vid behov vid uppdateringar.

Kärnan i DFX-mekanismen är den CDaoRecordset härledda klassens DoFieldExchange funktion. Den här funktionen skickar anrop till enskilda DFX-funktioner av lämplig åtgärdstyp. Innan du anropar DoFieldExchange de interna MFC-funktionerna anger du åtgärdstypen. I följande lista visas de olika åtgärdstyperna och en kort beskrivning.

Verksamhet Beskrivning
AddToParameterList Bygger PARAMETER-sats
AddToSelectList Bygger SELECT-sats
BindField Konfigurerar bindningsstruktur
BindParam Anger parametervärden
Fixup Anger en NULL-status
AllocCache Allokerar cache för orensad kontroll
StoreField Sparar aktuell post i cacheminnet
LoadField Återställer cacheminnet till medlemsvärden
FreeCache Frigör cache
SetFieldNull Anger fältstatus och värde till NULL
MarkForAddNew Markerar fält som är smutsiga om inte PSEUDO NULL
MarkForEdit Markerar fält som är smutsiga om de inte matchar cacheminnet
SetDirtyField Anger fältvärden som markerats som smutsiga

I nästa avsnitt förklaras varje åtgärd mer detaljerat för DFX_Text.

Den viktigaste funktionen att förstå om DAO-postfältutbytesprocessen är att den använder GetRows-funktionen hos CDaoRecordset-objektet. DAO-funktionen GetRows kan fungera på flera sätt. Den här tekniska anmärkningen beskriver GetRows bara kortfattat eftersom den ligger utanför den här tekniska anmärkningens omfattning. DAO GetRows kan fungera på flera sätt.

  • Den kan hämta flera poster och flera datafält samtidigt. Detta möjliggör snabbare dataåtkomst med utmaningen att hantera en stor datastruktur och lämpliga förskjutningar för varje fält och för varje post av data i strukturen. MFC drar inte nytta av den här mekanismen för hämtning av flera poster.

  • Ett annat sätt GetRows kan fungera på är att tillåta programmerare att specificera bindningsadresser för de hämtade datana i varje fälts datauppsättning.

  • DAO kommer också att återanropa anroparen för kolumner med variabel längd så att anroparen kan allokera minne. Den här andra funktionen har fördelen att minimera antalet kopior av data samt tillåta direkt lagring av data till medlemmar i en klass (den CDaoRecordset härledda klassen). Den andra mekanismen är den metod som MFC använder för att binda till datamedlemmar i CDaoRecordset härledda klasser.

Vad din anpassade DFX-rutin gör

Det framgår av den här diskussionen att den viktigaste åtgärden som implementeras i en DFX-funktion måste vara möjligheten att konfigurera de datastrukturer som krävs för att anropa GetRows. Det finns ett antal andra åtgärder som en DFX-funktion också måste stödja, men ingen så viktig eller komplex som korrekt förberedelse för anropet GetRows .

Användningen av DFX beskrivs i onlinedokumentationen. Det finns i princip två krav. Först måste medlemmar läggas till i den CDaoRecordset härledda klassen för varje bundet fält och parameter. Följande CDaoRecordset::DoFieldExchange bör åsidosättas. Observera att medlemmens datatyp är viktig. Det bör matcha data från fältet i databasen eller åtminstone kunna konverteras till den typen. Till exempel kan ett numeriskt fält i databasen, till exempel ett långt heltal, alltid konverteras till text och bindas till en CString medlem, men ett textfält i en databas kanske inte nödvändigtvis konverteras till en numerisk representation, till exempel långt heltal och bundet till en lång heltalsmedlem. DAO och Microsoft Jet-databasmotorn ansvarar för konverteringen (i stället för MFC).

Information om DFX_Text

Som tidigare nämnts är det bästa sättet att förklara hur DFX fungerar att arbeta med ett exempel. För detta ändamål bör en genomgång av det interna hos DFX_Text fungera ganska bra för att ge en grundläggande förståelse för DFX.

  • AddToParameterList

    Den här åtgärden skapar SQL PARAMETERS-satsen (""Parameters <param name>, <param type> ... ;) som krävs av Jet. Varje parameter namnges och skrivs (enligt beskrivningen i RFX-anropet). Se funktionsfunktionen CDaoFieldExchange::AppendParamType för att se namnen på de enskilda typerna. När det gäller DFX_Textär den typ som används text.

  • AddToSelectList

    Skapar SQL SELECT-satsen . Detta är ganska rakt fram eftersom kolumnnamnet som anges av DFX-anropet helt enkelt läggs till ("SELECT <column name>, ...").

  • BindField

    Den mest komplexa av åtgärderna. Som tidigare nämnts är det här som DAO-bindningsstrukturen GetRows som används konfigureras. Som du kan se i koden i DFX_Text typerna av information i strukturen inkluderar dao-typen som används (DAO_CHAR eller DAO_WCHAR i fallet med DFX_Text). Dessutom konfigureras även vilken typ av bindning som används. I ett tidigare avsnitt GetRows beskrevs endast kortfattat, men det var tillräckligt att förklara att den typ av bindning som används av MFC alltid är direkt adressbindning (DAOBINDING_DIRECT). Dessutom används motringningsbindning för kolumnbindning med variabel längd (t.ex DFX_Text. ) så att MFC kan styra minnesallokeringen och ange en adress med rätt längd. Vad detta innebär är att MFC alltid kan berätta för DAO "var" att placera data, vilket tillåter bindning direkt till medlemsvariabler. Resten av bindningsstrukturen fylls i med saker som adressen för återanropsfunktionen för minnesallokering och typen av kolumnbindning (bindning efter kolumnnamn).

  • BindParam

    Det här är en enkel åtgärd som anropar SetParamValue med parametervärdet som anges i parametermedlemmen.

  • Fixup

    Fyller i NULL-statusen för varje fält.

  • SetFieldNull

    Den här åtgärden markerar endast varje fältstatus som NULL och anger medlemsvariabelns värde till PSEUDO_NULL.

  • SetDirtyField

    Anropar SetFieldValue för varje fält som markerats som smutsigt.

Alla återstående åtgärder hanterar endast användning av datacachen. Datacachen är en extra buffert av data i den aktuella posten som används för att göra vissa saker enklare. Till exempel kan "smutsiga" fält identifieras automatiskt. Enligt beskrivningen i onlinedokumentationen kan den stängas av helt eller på fältnivå. Implementeringen av bufferten använder en karta. Den här kartan används för att matcha dynamiskt allokerade kopior av data med adressen till fältet "bound" (eller CDaoRecordset härledd datamedlem).

  • AllocCache

    Dynamiskt allokerar det cachelagrade fältvärdet och lägger till det på kartan.

  • FreeCache

    Tar bort det cachelagrade fältvärdet och tar bort det från kartan.

  • StoreField

    Kopierar det aktuella fältvärdet till datacachen.

  • LoadField

    Kopierar det cachelagrade värdet till fältmedlemmen.

  • MarkForAddNew

    Kontrollerar om det aktuella fältvärdet inte är NULL och markerar det som smutsigt om det behövs.

  • MarkForEdit

    Jämför aktuellt fältvärde med datacachen och markerar det som ändrat om det behövs.

Tips/Råd

Modellera dina anpassade DFX-rutiner på befintliga DFX-rutiner för standarddatatyper.

Se även

tekniska anteckningar efter nummer
tekniska anteckningar efter kategori