Sdílet prostřednictvím


Aktualizace sad řádků

Základní operací databáze je aktualizace nebo zápis dat do úložiště dat. V OLE DB je aktualizační mechanismus jednoduchý: aplikace příjemce nastaví hodnoty vázaných datových členů a pak tyto hodnoty zapíše do sady řádků; příjemce pak požádá o aktualizaci úložiště dat poskytovatelem.

Uživatelé mohou provádět následující druhy aktualizací dat sady řádků: nastavení hodnot sloupců v řádku, vložení řádku a odstranění řádku. K dokončení těchto operací, OLE DB Template třída CRowset implementuje IRowsetChange rozhraní a přepíše následující metody rozhraní:

  • SetData mění hodnoty sloupců v řádku sady řádků; odpovídá příkazu SQL UPDATE.

  • Vloží řádek do sady řádků. Je to stejné jako příkaz SQL INSERT.

  • Odstranění odstraní řádky ze sady řádků; odpovídá příkazu SQL DELETE.

Podpora operací aktualizace

Poznámka:

Průvodce příjemcem ATL OLE DB není v sadě Visual Studio 2019 a novější k dispozici. Funkci můžete přidat ručně. Další informace naleznete v tématu Vytvoření příjemce bez použití průvodce.

Když vytvoříte příjemce pomocí Průvodce příjemcem ATL OLE DB, můžete podporovat aktualizační operace zaškrtnutím jednoho nebo několika políček Změnit, Vložit a Odstranit. Pokud vyberete tyto možnosti, průvodce upraví kód odpovídajícím způsobem tak, aby podporoval vámi zvolený typ změn. Pokud ale průvodce nepoužíváte, musíte nastavit následující vlastnosti sady řádků tak, aby VARIANT_TRUE 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.

Vlastnosti nastavíte 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ěny, vložení nebo odstranění můžou selhat, pokud jeden nebo více sloupců není zapisovatelný. Upravte mapu kurzoru tak, aby tento problém opravil.

Nastavení dat v řádcích

CRowset::SetData nastavuje hodnoty dat v jednom nebo více sloupcích aktuálního řádku. Následující kód nastaví hodnoty datových členů svázaných se sloupci Name a Units in Stock tabulkou Products a potom tyto hodnoty zapíše SetData do 100. řá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 sad řádků

CRowset::Insert vytvoří a inicializuje nový řádek pomocí dat z přístupového objektu. Insert vytvoří zcela nový řádek za aktuálním řádkem; musíte určit, jestli se má aktuální řádek navýšit na další řádek, nebo ho nechat beze změny. Provedete to nastavením parametru bGetRow :

HRESULT Insert(int nAccessor = 0, bool bGetRow = false)
  • false (výchozí hodnota) určuje, že aktuální řádek se zvýší na další řádek (v takovém případě odkazuje na vložený řádek).

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

Následující kód nastaví hodnoty datových členů vázaných na sloupce tabulky Products a potom zavolá vložení Insert nového řádku s těmito hodnotami za 100. řádek sady řádků. Doporučujeme nastavit všechny hodnoty sloupců, aby se zabránilo nedefinovaným datům v novém řá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();

Podrobnější příklad najdete v tématu CRowset::Insert.

Další informace o nastavení datových členů stavu a délky naleznete v tématu Členové dat o stavu pole v Průvodci generované přístupové objekty.

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

CRowset::D elete odstraní aktuální řádek ze sady řádků. Následující volání Delete kódu pro odebrání 100. řá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

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

Okamžité a odložené aktualizace

Pokud neurčíte jinak, volání , SetDataInserta Delete metody aktualizují úložiště dat okamžitě. Aktualizace však můžete odložit tak, aby příjemce uložil všechny změny v místní mezipaměti a pak je při volání některé z následujících metod aktualizace 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 Update volání.

  • CRowset::UpdateAll přenese všechny čekající změny provedené ve všech řádcích od posledního načtení nebo Update volání.

Aktualizace, která se používá metodami aktualizace, má specifický význam provádění změn v příkazu a není zaměňována s příkazem SQL UPDATE (SetData je ekvivalentem příkazu SQL UPDATE ).

Odložené aktualizace jsou užitečné například v situacích, jako je řada bankovních transakcí; Pokud je jedna transakce zrušena, můžete vrátit změnu zpět, protože neodesíláte řadu změn, dokud nebude potvrzena poslední transakce. Poskytovatel může také sbalit změny do jednoho síťového volání, což je efektivnější.

Pokud chcete podporovat odložené aktualizace, musíte vlastnost nastavit DBPROP_IRowsetChange spolu s vlastnostmi popsanými v operacích podpory aktualizací:

pPropSet->AddProperty(DBPROP_IRowsetUpdate, true);

Když zavoláte Update nebo UpdateAll, metody přenesou změny z místní mezipaměti do úložiště dat a pak vymažou místní mezipaměť. Protože aktualizace přenáší změny pouze pro aktuální řádek, je důležité, aby vaše aplikace sledovala, který řádek se má aktualizovat a kdy ho aktualizovat. 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

Pokud chcete zajistit, aby se nepřenesly čekající změny, měli byste před přesunutím na jiný řádek volat Update . Pokud je to ale zdlouhavé nebo neefektivní, například když vaše aplikace potřebuje aktualizovat stovky řádků, můžete použít UpdateAll k aktualizaci všech řádků najednou.

Pokud například ve výše uvedeném kódu chybí první Update volání, řádek 100 zůstane beze změny, zatímco řádek 101 se změní. Po tomto bodu bude aplikace muset zavolat UpdateAll nebo přejít zpět na řádek 100 a volat Update , aby se tento řádek aktualizoval.

A konečně je jedním z hlavních důvodů, proč odložit změny, je možnost je vrátit zpět. Volání CRowset::Undo vrátí stav místní mezipaměti změn do stavu úložiště dat před provedením čekajících změn. Je důležité si uvědomit, že Undo se stav místní mezipaměti nevrací o jeden krok (stav před pouze poslední změnou). Místo toho vymaže místní mezipaměť pro tento řádek. Undo Týká se to také pouze aktuálního řádku.

Viz také

Práce s šablonami příjemců OLE DB
CRowset – třída
IRowsetChange