Atualizando conjuntos de linhas
É uma operação de banco de dados muito básico atualizar ou gravar dados para o armazenamento de dados. Em OLE DB, o mecanismo de atualização é simple: seu aplicativo de consumidor define os valores dos membros de dados vinculado e, em seguida, grava esses valores para o conjunto de linhas; o consumidor solicita que o provedor de atualizar o armazenamento de dados.
Os consumidores podem executar os seguintes tipos de atualizações no conjunto de linhas dados: definindo valores de coluna em uma linha, inserindo uma linha e excluir uma linha. Para executar essas operações, a classe de modelo do OLE DB CRowset implementa o IRowsetChange interface e substitui os seguintes métodos de interface:
SetData altera os valores de coluna em uma linha de um conjunto de linhas; é equivalente ao comando de atualização de SQL.
Inserir insere uma linha um conjunto de linhas; é equivalente ao comando SQL inserir.
Excluir exclui as linhas de um conjunto de linhas; é equivalente ao comando Excluir do SQL.
Suporte a operações de atualização
Quando você cria um consumidor com o ATL OLE DB consumidor assistente, você pode oferecer suporte as operações de atualização, selecionando uma ou mais das três caixas de seleção alteração, Inserir, e Excluir. Se você selecionar esses, o assistente modifica o código adequadamente para suportar o tipo de alterações que você escolher. No entanto, se você não usar o assistente, você precisará definir as seguintes propriedades do conjunto de linhas VARIANT_TRUE para oferecer suporte a atualizações:
DBPROPVAL_UP_CHANGE permite que você altere os valores de dados em uma linha.
DBPROPVAL_UP_INSERT permite que você inserir uma linha.
DBPROPVAL_UP_DELETE lhe permite excluir uma linha.
Você definir as propriedades da seguinte maneira:
CDBPropSet ps(DBPROPSET_ROWSET);
ps.AddProperty(DBPROP_IRowsetChange, true)
ps.AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_DELETE)
As operações de exclusão, inserção ou alteração poderão falhar se uma ou mais colunas não é gravável. Modifique o mapa de cursor para corrigir isso.
Dados de configuração em linhas
CRowset::SetData define os valores de dados de uma ou mais colunas da linha atual. O código a seguir define os valores dos membros de dados acoplados às colunas "Nome" e "Unidades em estoque" a tabela Produtos e chamadas SetData para gravar esses valores para a linha de centésima do conjunto de linhas:
// 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( );
A inserção de linhas em conjuntos de linhas
CRowset::Insert cria e inicializa uma nova linha usando os dados de o acessador. Inserir cria uma linha totalmente nova, após a linha atual. Você precisa especificar se deseja incrementar a linha atual para a próxima linha ou deixá-la inalterada. Fazer isso, definindo a bGetRow parâmetro:
HRESULT Insert(int nAccessor = 0, bool bGetRow = false)
False (o valor padrão) Especifica que a linha atual é incrementado para a próxima linha (caso no qual ele aponta para a linha inserida).
True Especifica que a linha atual permanecer onde está.
O código a seguir define os valores de membros de dados acoplados às colunas da tabela Produtos e chama Inserir para inserir uma nova linha com esses valores depois da linha de centésima do conjunto de linhas. É recomendável que você defina todos os valores de coluna para evitar dados indefinidos na nova linha:
// 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( );
Para obter um exemplo mais detalhado, consulte CRowset::Insert.
Para obter mais informações sobre como definir o status e o comprimento de membros de dados, consulte Membros de dados do campo Status nos acessadores de Wizard-Generated.
A exclusão de linhas de conjuntos de linhas
CRowset::Delete exclui a linha atual do conjunto de registros. O seguinte código chama Excluir para remover a linha centésima do conjunto de linhas:
// 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( );
Atualizações imediatas e adiadas
A menos que você especifique o contrário, chama o SetData, Inserir, e Excluir métodos de atualizar o armazenamento de dados imediatamente. No entanto, você pode adiar atualizações, para que o consumidor armazena todas as alterações em um cache local e, em seguida, transfere para o armazenamento de dados quando você chamar um dos seguintes métodos de atualização:
CRowset::Update transfere qualquer alteração feita na linha atual desde a última busca pendente ou atualização chamar nele.
CRowset::UpdateAll transfere qualquer alteração feita em todas as linhas, desde a última busca pendente ou atualização chamar nele.
Observação Essa atualização, conforme usado pelos métodos de atualização, tem um significado específico de fazer alterações no comando e não deve ser confundido com o comando de atualização de SQL (SetData é equivalente ao comando SQL Atualizar).
Atualizações adiadas são úteis, por exemplo, em situações como, por exemplo, uma série de transações bancárias; Se uma transação for cancelada, você pode desfazer a alteração, porque você não enviar a série de alterações até depois que o último é confirmada. Além disso, o provedor pode agrupar as alterações na chamada de uma rede, o que é mais eficiente.
Para oferecer suporte a atualizações adiadas, você deve definir o DBPROP_IRowsetChange propriedade, além das propriedades descritas em "Suporte a operações de atualização":
pPropSet->AddProperty(DBPROP_IRowsetUpdate, true);
Quando você chamar atualização ou UpdateAll, os métodos de transferência de alterações do cache local para o armazenamento de dados e, em seguida, apagar o cache local. Como atualizar transfere somente as alterações na linha atual, é importante que seu aplicativo manter o controle de qual linha update e quando atualizá-lo. O exemplo a seguir mostra como duas linhas consecutivas de atualização:
// 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
Para garantir que as alterações pendentes são transferidas, você deve chamar atualização antes de passar para outra linha. No entanto, quando isso é entediante ou ineficiente, por exemplo, quando seu aplicativo precisa para atualizar a centenas de linhas, você pode usar UpdateAll para atualizar todas as linhas ao mesmo tempo.
Por exemplo, se o primeiro atualização chamada estavam faltando no código acima, a linha 100 permanecem inalterada, enquanto linha 101 seria alterada. Depois desse ponto, seu aplicativo tem que chamar UpdateAll ou voltar para a linha 100 e a chamada atualização para aquela linha a ser atualizado.
Finalmente, um motivo principal para adiar a alterações é ser capaz de desfazê-las. Chamando CRowset::Undo reverte o estado do cache local de alteração para o estado do armazenamento de dados antes de quaisquer alterações pendentes foram feitas. É importante observar que Desfazer não reverter o estado do cache local, uma etapa (o estado antes apenas da alteração mais recente); em vez disso, ele limpa o cache local para aquela linha. Além disso, Desfazer afeta somente a linha atual.