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.

Consulte também

Referência

Trabalhando com modelos de consumidor do OLE DB

CRowset Class

IRowsetChange