Sdílet prostřednictvím


Aktualizace sad řádků

Velmi základní databázová operace je aktualizace nebo zápis dat do úložiště dat. V rozhraní technologie OLE DB je jednoduchý mechanismus aktualizace: Aplikace příjemce nastaví hodnoty vázaných datových členů a poté zapíše tyto hodnoty do sady řádků; příjemce poté požádá zprostředkovatele, aby aktualizoval úložiště dat.

Příjemci mohou provádět následující druhy aktualizací dat řádků: nastavení hodnot buněk v řádku, vkládání řádku a odstraňování řádku. Chcete-li provést tyto operace, třída šablony CRowset z technologie OLE DB implementuje rozhraní IRowsetChange a přepíše následující metody rozhraní:

  • SetData změní hodnoty sloupce v řádku u sady řádků; je ekvivalentní příkazu SQL UPDATE.

  • Insert vloží řádek do sady řádků; je ekvivalentní příkazu SQL INSERT.

  • Delete odstraní řádky ze sady řádků; je ekvivalentní příkazu SQL DELETE.

Podpora operací aktualizace

Vytvoříte-li příjemce pomocí průvodce příjemce knihovny ATL technologie OLE DB, může podporovat operace aktualizace jestliže zaškrtnete jedno nebo více ze tří zaškrtávacích políček Change, Insert a Delete. Vyberete-li tyto tři zaškrtávací políčka, průvodce vhodně upraví kód, aby podporoval typ změn, které zvolíte. Nicméně pokud nepoužijete průvodce, musíte nastavit následující vlastnosti sady řádků na VARIANT_TRUE, aby podporovaly aktualizace:

  • DBPROPVAL_UP_CHANGE umožňuje změnit hodnoty dat v řádku.

  • DBPROPVAL_UP_INSERT umožňuje vložit řádek.

  • DBPROPVAL_UP_DELETE umožňuje odstranit řádek.

Nastavte vlastnosti takto:

CDBPropSet ps(DBPROPSET_ROWSET);
ps.AddProperty(DBPROP_IRowsetChange, true)
ps.AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_DELETE)

Operace změnit, vložit nebo odstranit může selhat, pokud do jedné, nebo více buněk nelze zapisovat. Abyste toto opravili, změňte vaši mapu ukazatelů.

Nastavení dat v řádcích

CRowset::SetData nastaví hodnoty dat v jedné nebo ve více buňkách aktuálního řádku. Následující kód nastaví hodnoty datových členů, které jsou vázány na sloupce "Name" a "Units in Stock" tabulky Products a pak zavolá SetData, která zápíše tyto hodnoty do stého řádku sady řádků:

// Instantiate a rowset based on the user record class
CTable<CAccessor<CProductAccessor> > product;
CSession session;

// Open the rowset and move to the 100th row
product.Open(session, "Product", &ps, 1);  // ps is the property set
product.MoveToBookmark(&bookmark, 0);      // Assume that bookmark is set to 100th row

// Change the values of columns "Name" and "Units in Stock" in the current row of the Product table
_tcscpy_s( product.m_ProductName, product.m_sizeOfProductName,
           _T( "Candle" ) );
product.m_UnitsInStock = 10000;

// Set the data
HRESULT hr = product.SetData( );

Vkládání řádků do sady řádků

CRowset::Insert vytvoří a inicializuje nový řádek pomocí dat z přistupujícího objektu. Insert vytvoří zcela nový řádek za aktuálním řádkem; je třeba určit, zda chcete zvýšit aktuální řádek na další řádek nebo ponechat beze změny. Toto provedete nastavením parametru bGetRow:

HRESULT Insert(int nAccessor = 0, bool bGetRow = false)
  • Hodnota false (výchozí hodnota) určuje, že bude aktuální řádek posunut na další řádek (v tomto případě ukazuje na vložený řádek).

  • true určí, že aktuální řádek zůstane tam, kde je.

Následující kód nastaví hodnoty datových členů, které jsou vázány na sloupce tabulky Products a pak zavolá Insert, která vloží nový řádek s těmito hodnotami za stý řádek sady řádků. Doporučujeme, abyste nastavili všechny hodnoty buněk, abyste předešli nedefinovaným datům v řádku:

// Instantiate a rowset based on the user record class
CTable<CAccessor<CProductAccessor> > product;
CSession session;

// Open the rowset and move to the 100th row
product.Open(session, "Product", &ps, 1);  // ps is the property set
product.MoveToBookmark(&bookmark, 0);      // Assume that bookmark is set to 100th row

// Set the column values for a row of the Product table, then insert the row
product.m_ProductID = 101;
_tcscpy_s( product.m_ProductName, product.m_sizeOfProductName,
           _T( "Candle" ) );
product.m_SupplierID = 27857;
product.m_CategoryID = 372;
_tcscpy_s( product.m_QuantityPerUnit, product.m_sizeOfQuantityPerUnit,
           _T( "Pack of 10" ) );
product.m_UnitPrice = 20;
product.m_UnitsInStock = 10000;
product.m_UnitsOnOrder = 5201;
product.m_ReorderLevel = 5000;
product.m_Discontinued = false;

// You must also initialize the status and length fields before setting/inserting data
// Set the column status values
m_dwProductIDStatus = DBSTATUS_S_OK;
m_dwProductNameStatus = DBSTATUS_S_OK;
m_dwSupplierIDStatus = DBSTATUS_S_OK;
m_dwCategoryIDStatus = DBSTATUS_S_OK;
m_dwQuantityPerUnitStatus = DBSTATUS_S_OK;
m_dwUnitPriceStatus = DBSTATUS_S_OK;
m_dwUnitsInStockStatus = DBSTATUS_S_OK;
m_dwUnitsOnOrderStatus = DBSTATUS_S_OK;
m_dwReorderLevelStatus = DBSTATUS_S_OK;
m_dwDiscontinuedStatus = DBSTATUS_S_OK;

// Set the column length value for column data members that are not fixed-length types.
// The value should be the length of the string that you are setting.
m_dwProductNameLength = 6;             // "Candle" has 6 characters
m_dwQuantityPerUnitLength = 10;        // "Pack of 10" has 10 characters

// Insert the data
HRESULT hr = product.Insert( );

Pro podrobnější příklad viz CRowset::Insert.

Další informace o nastavení stavu a délky datových členů naleznete v tématu Field Status Data Members in Wizard-Generated Accessors.

Odstranění řádků ze sady řádků

CRowset::Delete odstraní aktuální řádek ze sady řádků. Následující kód volá Delete, aby odebrala stý řádek sady řádků:

// Instantiate a rowset based on the user record class
CTable<CAccessor<CProductAccessor> > product;
CSession session;

// Open the rowset and move to the 100th row
product.Open(session, "Product", &ps, 1);  // ps is the property set
product.MoveToBookmark(&bookmark, 0);      // Assume that bookmark is set to 100th row

// Delete the row
HRESULT hr = product.Delete( );

Okamžité a odložené aktualizace

Pokud neurčíte jinak, volání metod SetData, Insert a Delete okamžitě aktualizuje úložiště dat. Aktualizace se však může odložit tak, aby příjemce uložil všechny změny v místní mezipaměťi a při volání následujících metod aktualizace je přenese do úložiště dat:

  • CRowset::Update přenese všechny čekající změny provedené na aktuálním řádku od posledního načtení nebo můžete zavolat Update.

  • CRowset::UpdateAll přenese všechny čekající změny provedené na všech řádcích od posledního načtení nebo můžete zavolat Update.

Poznámka: tato aktualizace, jak je používaná metodami aktualizace, má zvláštní význam provádění změn u příkazu a nelze ji zaměňovat s příkazem SQL UPDATE (SetData je ekvivalentní příkazu SQL UPDATE).

Odložené aktualizace jsou užitečné například v situacích, jako je například řada bankovních transakcí; pokud je jedna transakce zrušena, můžete změnu vrátit, protože neodešlete řadu změn až do té doby, než je poslední transakce potvrzena. Poskytovatel také může svázat změny do jednoho síťového volání, které je efektivnější.

Chcete-li podporovat odložené aktualizace, musíte navíc nastavit vlastnost DBPROP_IRowsetChange vedle vlastností popsaných v "Podpora operací aktualizace":

   pPropSet->AddProperty(DBPROP_IRowsetUpdate, true);

Pokud voláte Update nebo UpdateAll, metody přenesou změny z místní mezipaměťi do úložiště dat a potom vymažou místní mezipaměť. Aktualizace přenese změny pouze pro aktuální řádek, proto je důležité, aby si vaše aplikace udržela přehled o tom, který řádek má aktualizovat a kdy. Následující příklad ukazuje, jak aktualizovat dva po sobě jdoucí řádky:

// Instantiate a rowset based on the user record class
CTable<CAccessor<CProductAccessor> > product;
CSession session;

// Open the rowset and move to the 100th row
product.Open(session, "Product", &ps, 1);  // ps is the property set
product.MoveToBookmark(&bookmark, 0);      // Assume that bookmark is set to 100th row

// Change the values of columns "Name" and "Units in Stock" in the 100th row of the Product table
_tcscpy_s( product.m_ProductName, product.m_sizeOfProductName,
           _T( "Wick" ) );
product.m_UnitsInStock = 10000;
HRESULT hr = product.SetData( );  // No changes made to row 100 yet
product.Update();                 // Update row 100 now

// Change the values of columns "Name" and "Units in Stock" in the 101st row of the Product table
product.MoveNext( );
_tcscpy_s( product.m_ProductName, product.m_sizeOfProductName
           _T( "Wax" ) );
product.m_UnitsInStock = 500;
HRESULT hr = product.SetData( );  // No changes made to row 101 yet
product.Update();                 // Update row 101 now

Chcete-li zajistit, že budou čekající změny přeneseny, měli byste zavolat Update před přesunutím se na jiný řádek. Pokud je to však únavné nebo neefektivní, například pokud aplikace potřebuje aktualizovat stovky řádků, můžete použít UpdateAll, chcete-li aktualizovat všechny řádky najednou.

Například pokud by nebylo první volání Update ve výše uvedeném kódu, řádek 100 by zůstal nezměněn, zatímco řádek 101 by byl změněn. Po tomto bodě by měla vaše aplikace buď volat UpdateAll nebo se přesunout zpět na řádek 100 a volat Update, aby byl tento řádek aktualizován.

Nakonec jeden z hlavních důvodů odložení změny je možnost vrácení se. Volání CRowset::Undo vrátí zpět stav změn místní mezipaměťi do stavu, který se nacházel v úložišti dat před tím, než byly nějaké čekající změny provedeny. Je důležité si povšimnout, že Undo nevrátí stav místní mezipaměťi o jeden krok zpět (stav před poslední změnou); místo toho vymaže místní mezipaměť pro daný řádek. Navíc Undo ovlivní pouze aktuální řádek.

Viz také

Odkaz

Práce s šablonami příjemců OLE DB

CRowset Class

IRowsetChange