Atualizando conjuntos de linhas
É uma operação de banco de dados muito básico atualizar ou gravar dados para armazenamento de dados.Em OLE DB, o mecanismo de atualização é simple: o aplicativo de consumidor define os valores de membros de dados ligados e grava esses valores para o conjunto de linhas; o consumidor solicita que o provedor atualizar o armazenamento de dados.
Os consumidores podem realizar os seguintes tipos de atualizações no conjunto de linhas dados: definição de valores de coluna em uma linha, inserindo uma linha e excluir uma linha.Para executar essas operações, a classe de modelo de BD OLE 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 UPDATE SQL.
Inserir insere uma linha em um conjunto de linhas; é equivalente ao comando Inserir SQL.
Excluir exclui linhas do conjunto de linhas; é equivalente ao comando Excluir SQL.
Suporte a operações de atualização
Quando você criar um consumidor com o ATL OLE DB consumidor assistente, pode oferecer suporte as operações de atualização, selecionando uma ou mais das três caixas de seleção Alterar, 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ê precisa definir as seguintes propriedades de 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 permite que você excluir uma linha.
Você pode 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)
Alterar, inserir ou excluir operações podem falhar se uma ou mais colunas não é gravável.Modificar o mapa de cursor para corrigir isso.
Dados de configuração em linhas
CRowset::SetData define valores de dados em 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" da tabela Produtos e chama SetData para gravar esses valores para a centésimo linha 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( );
Inserindo linhas em conjuntos de linhas
CRowset::Insert cria e inicializa uma nova linha usando dados do acessador.Inserir cria uma inteiramente nova linha depois da linha atual; Você precisa especificar se deseja incrementar a linha atual para a próxima linha ou deixá-la inalterada.Fazer isso configurando 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 dos membros de dados acoplados às colunas da tabela Produtos e chama Inserir para inserir uma nova linha com esses valores depois da linha centésimo do conjunto de linhas.É recomendável que você defina todos os valores de coluna para evitar indefinidos dados 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 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.
Excluir linhas de conjuntos de linhas
CRowset::Delete exclui a linha atual do conjunto de linhas.O seguinte código chama Excluir para remover a linha centésimo 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 transfere-os para o armazenamento de dados quando você chamar um dos seguintes métodos de atualização:
CRowset::Update transfere qualquer pendente alterações feitas à linha atual desde a última busca ou atualização chamar nele.
CRowset::UpdateAll transfere qualquer pendente alterações feitas desde a última busca todas as linhas ou atualização chamar nele.
Observe que a atualização, conforme usado pelos métodos de atualização, tem significado específico de fazer alterações no comando e não deve ser confundido com o comando UPDATE 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 reunir as alterações na chamada de uma rede, 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 transferir as alterações do cache local para o armazenamento de dados e, em seguida, limpe o cache local.Como atualizar transfere somente as alterações da linha atual, é importante que seu aplicativo controlar de qual linha update e quando atualizá-lo.O exemplo a seguir mostra como atualizar duas linhas consecutivas:
// 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 atualizar centenas de linhas, você pode usar UpdateAll para atualizar todas as linhas de uma vez.
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, o aplicativo tem que chamar UpdateAll ou mover de volta para a linha 100 e chamada atualização para aquela linha a ser atualizado.
Finalmente, uma razão principal para adiar alterações é ser capaz de desfazê-las.Chamando CRowset::Undo reverte o estado do cache local alterar 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 da última alteração); em vez disso, ele limpa o cache local para aquela linha.Além disso, Desfazer afeta somente a linha atual.