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í , SetData
Insert
a 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