ID do artigo: 320301 - Última revisão: domingo, 1 de fevereiro de 2004 - Revisão: 3.4
COMO: Atualizar dados pai-filho com uma coluna de identidade de um aplicativo do Windows Forms usando uma Web Service in Visual translation from VPE for Csharp .NET
Dica do SistemaEste artigo aplica-se a um sistema operativo diferente do que está a utilizar. Foi desactivado o conteúdo do artigo, que pode não ser relevante para si.
Este artigo passo a passo descreve como recuperar um objeto DataSet de um serviço da Web, como enviar DiffGram atualizações para o serviço da Web e, em seguida, como mesclar DiffGram atualizado o cliente DataSet de volta. Esse processo envolve as seguintes etapas:
O aplicativo cliente recupera um objeto de DataSet com dois objetos DataTable em uma relação pai-filho do serviço da Web. A DataTable pai possui uma coluna de identidade/AutoNumeração como chave primária.
O aplicativo cliente, o usuário pode adicionar, excluir e modificar registros pai e filho registros. Novos registros pai recebem um temporário valor de chave primário que é gerado localmente.
O aplicativo cliente envia as alterações de volta para a Web service como um DiffGram.
O serviço da Web atualiza o banco de dados, recupera os valores de chaves primária reais para novos registros pai e, em seguida, propaga os valores da chave que são alterados para os registros filho.
O aplicativo cliente recebe os valores atualizados de serviço da Web e mescla os valores atualizados local DataSet de volta.
Para obter informações adicionais sobre como atualizar uma única tabela usando um serviço da Web, clique no número abaixo para ler o artigo na Base de dados de Conhecimento da Microsoft:
310143
(http://support.microsoft.com/kb/310143/EN-US/
)
COMO: Atualizar dados do servidor por meio de uma Web Service usando o ADO.NET e Visual translation from VPE for Csharp .NET
A lista a seguir descreve o hardware recomendado, software, infra-estrutura de rede e service packs são necessários:
Microsoft Windows 2000 Professional, Windows 2000 Server, Windows 2000 Advanced Server ou Windows NT 4.0 Server
Microsoft Visual Studio .NET
Este artigo pressupõe que você esteja familiarizado com os seguintes tópicos:
O Visual Studio .NET
Conceitos básicos do ADO.NET e sintaxe
Conceitos básicos do ASP.NET e sintaxe
Os exemplos de código neste artigo use http://localhost como o servidor Web. Além disso, as amostras de código usam o banco de dados Northwind como o banco de dados. O banco de dados Northwind está incluído no Microsoft SQL Server.
Para criar um novo projeto do Visual translation from VPE for Csharp ASP.NET Web Service, execute essas etapas:
Inicie o Visual Studio NET..
No menu arquivo , aponte para novo e, em seguida, clique em Project .
Clique em projetos do Visual translation from VPE for Csharp em Tipos de projeto e, em seguida, clique em ASP.NET Web Service em modelos .
Na caixa local , o local padrão é exibido como http://localhost/WebService1. Digite a URL para o servidor (por exemplo, http://localhost executa serviço da Web no seu servidor Web local). Substituir WebService1 com CSharpUpdateData . A URL na caixa local deve aparecer da seguinte maneira:
http://localhost/CSharpUpdateData
Para fechar a caixa de diálogo New Project , clique em OK .
Em Service1.asmx.cs[Design] página, alterne para modo de exibição código. Observe que a janela de código para o serviço da Web é exibida.
Na parte superior da janela código, adicione a instrução a seguir usando :
using System.Data.SqlClient;
Adicione o seguinte para a implementação da classe Service1:
[WebMethod]
public DataSet GetData()
{
SqlConnection conn = new SqlConnection ("server=vcdb02;uid=sa;pwd=ricka;database=northwind");
//Pull back the recent orders for the parent rows.
SqlDataAdapter daOrder = new SqlDataAdapter("SELECT * FROM Orders WHERE OrderDate >= '05/01/1998'",conn);
//Get only the appropriate child rows for the parent rows.
SqlDataAdapter daDetails = new SqlDataAdapter("SELECT * FROM [Order Details] WHERE OrderID in ( SELECT OrderID FROM Orders WHERE OrderDate >= '05/01/1998')",conn);
DataSet ds = new DataSet();
try
{
//Fill DataSet, and then set DataRelation to move through the DataGrid.
conn.Open();
daOrder.FillSchema(ds,SchemaType.Mapped,"Orders");
daOrder.Fill(ds,"Orders");
daDetails.FillSchema(ds,SchemaType.Mapped,"Details");
daDetails.Fill(ds,"Details");
ds.Relations.Add("OrdDetail", ds.Tables["Orders"].Columns["OrderID"], ds.Tables["Details"].Columns["OrderID"]);
DataColumn dc = ds.Tables["Orders"].Columns["OrderID"];
dc.AutoIncrement = true;
dc.AutoIncrementSeed = -1;
dc.AutoIncrementStep = -1;
}
catch(SqlException ex)
{
Console.Write (ex.Message.ToString ());
Console.Write(ex.InnerException.ToString ());
}
return ds;
}
[WebMethod]
public DataSet UpdateData(DataSet ds)
{
SqlConnection conn = new SqlConnection ("server=vcdb02;uid=sa;pwd=ricka;database=northwind");
//Pull back the recent orders for the parent rows.
SqlDataAdapter daOrders = new SqlDataAdapter("SELECT * FROM Orders WHERE OrderDate >= '05/01/1998'",conn);
//Get only the appropriate child rows for the parent rows.
SqlDataAdapter daDetails = new SqlDataAdapter("SELECT * FROM [Order Details] WHERE OrderID in ( SELECT OrderID FROM Orders WHERE OrderDate >= '05/01/1998')",conn);
try
{
conn.Open();
// Get commands for the Orders table.
// Reselect record after insert to get new Identity value.
// You must get the schema, which you did in GetData(), before you get commands;
// otherwise, the Command builder tries to insert new rows, based
// on the Identity column.
SqlCommandBuilder cb = new SqlCommandBuilder(daOrders);
daOrders.DeleteCommand = cb.GetDeleteCommand();
daOrders.UpdateCommand = cb.GetUpdateCommand();
daOrders.InsertCommand = cb.GetInsertCommand();
daOrders.InsertCommand.CommandText = String.Concat(daOrders.InsertCommand.CommandText, "; Select * From Orders Where OrderID = @@IDENTITY");
//UpdateRowSource tells the DataAdapter that there will be a re-selected record.
daOrders.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;
//cb = null;
// Get commands for the Order Details table.
// Must set the QuotePrefix and QuoteSuffix;
// otherwise, the CommandBuilder does not put brackets ([])
// around the table name.
SqlCommandBuilder cb1 = new SqlCommandBuilder(daDetails);
cb1.QuotePrefix = "[";
cb1.QuoteSuffix = "]";
daDetails.DeleteCommand = cb1.GetDeleteCommand();
daDetails.InsertCommand = cb1.GetInsertCommand();
daDetails.UpdateCommand = cb1.GetUpdateCommand();
// Create a new DataAdapter based on the original one to prevent the
// CommandBuilder from modifying the SQL statements,
// specifically the custom InsertCommand.
// You do not need this if you roll your own commands and parameters
// or if you use the Visual Tools to do it.
SqlDataAdapter daOrd2 = new SqlDataAdapter();
daOrd2.DeleteCommand = daOrders.DeleteCommand;
daOrd2.InsertCommand = daOrders.InsertCommand;
daOrd2.UpdateCommand = daOrders.UpdateCommand;
// Use a delegate to prevent AcceptChanges from occurring on Deletes and Inserts.
// This is for a limitation of the DataAdapter; see Q313540.
daOrd2.RowUpdated += new SqlRowUpdatedEventHandler(OnOrd1RowUpdated);
daDetails.RowUpdated += new SqlRowUpdatedEventHandler(OnDetailsRowUpdated);
daDetails.Update(GetDeletedRows(ds.Tables["Details"]));
daOrd2.Update(GetDeletedRows(ds.Tables["Orders"]));
DataRow [] dsArray = ds.Tables["Orders"].Select("", "", DataViewRowState.ModifiedCurrent);
daOrd2.Update(ds.Tables["Orders"].Select("", "", DataViewRowState.ModifiedCurrent));
daDetails.Update(ds.Tables["Details"].Select("", "", DataViewRowState.ModifiedCurrent));
daOrd2.Update(ds.Tables["Orders"].Select("", "", DataViewRowState.Added));
ds.EnforceConstraints = false;
daDetails.Update(ds.Tables["Details"].Select("","", DataViewRowState.Added));
ds.EnforceConstraints = true;
conn.Close();
}
catch(SqlException ex)
{
Console.Write (ex.Message.ToString ());
Console.Write(ex.InnerException.ToString ());
}
return ds;
}
protected static void OnOrd1RowUpdated(object sender, SqlRowUpdatedEventArgs args)
{
if(args.StatementType == StatementType.Insert || args.StatementType == StatementType.Delete )
args.Status = UpdateStatus.SkipCurrentRow;
}
protected static void OnDetailsRowUpdated(object sender, SqlRowUpdatedEventArgs args)
{
if(args.StatementType == StatementType.Insert )
{
// Do not allow the AcceptChanges to occur on this row.
args.Status = UpdateStatus.SkipCurrentRow;
// Get the current, actual primary key value so that you can plug it back
// in after you get the correct original value that was generated for the child row.
int currentkey = (int)args.Row["OrderID"];
// This is where you get a correct original value key that is stored to the child row.
// You pull the original, pseudo key value from the parent, plug it in as the child row's primary key
// field, and then accept changes on it. Specifically, this is why you turned off EnforceConstraints.
args.Row["OrderID"] = args.Row.GetParentRow("OrdDetail")["OrderID",DataRowVersion.Original];
args.Row.AcceptChanges();
// Store the actual primary key value in the foreign key column of the child row.
args.Row["OrderID"] = currentkey;
}
if(args.StatementType == StatementType.Delete )
args.Status = UpdateStatus.SkipCurrentRow;
}
private DataRow [] GetDeletedRows(DataTable dt)
{
DataRow [] dr ;
if(dt == null)
return null;
dr = dt.Select("","",DataViewRowState.Deleted );
if(dr.Length ==0 || dr[0] != null)
return dr;
// Workaround:
// With a remoted DataSet, Select returns the array elements
// that are filled with Nothing/null instead of DataRow objects.
for(int i=0; i < (int)dt.Rows.Count; i++)
{
if(dt.Rows[i].RowState ==DataRowState.Deleted )
dr[i]=dt.Rows[i];
}
return dr;
}
Modificar as seqüências SqlConnection se conectar ao servidor que está executando o SQL Server.
Pressione F5 para compilar e executar o serviço da Web. Observe que uma página da Web é retornada com a URL http://localhost/CSharpUpdateData/Service1.asmx. Nesta página da Web, você pode interagir com o serviço da Web do Microsoft Internet Explorer.
Na página da Web Service1.asmx, clique em GetData . Observe que uma página da Web é retornada que exibe detalhes sobre o método GetData da Web.
Para criar um novo projeto do Visual translation from VPE for Csharp Windows Application, execute essas etapas:
No menu arquivo no Visual Studio. NET, aponte para novo e, em seguida, clique em Project .
Na caixa de diálogo New Project , clique em projetos do Visual translation from VPE for Csharp em Project Types e clique em Windows Application em modelos . Por padrão, o Form1 é adicionado para o projeto.
Arraste um controle Button e um controle DataGrid da caixa de ferramentas para Form1. Por padrão, os controles são chamados button1 e dataGrid1 respectivamente.
Altere a propriedade Name do button1 para btnSave e, em seguida, altere a propriedade texto de button1 para Salvar .
No menu Project , clique em Add Web Reference . Digite a URL para seu Web service (no caso, tipo http://localhost/CSharpUpdateData/Service1.asmx ), pressione ENTER e, em seguida, clique em Add Reference . Observe que a entrada para essa referência da Web aparece no Solution Explorer.
Adicione o seguinte código à classe Form1 para declarar um membro de nível de formulário para o DataSet :
private System.Data.DataSet ds;
Clique duas vezes o formulário para alternar para modo de exibição código e observar que o Visual Studio .NET gera o método Form1_Load . Adicione o seguinte código para o método Form1_Load :
Abra a janela código do botão Salvar e, em seguida, adicione o seguinte código ao manipulador de evento btnSave_Click :
localhost.Service1 sv = new localhost.Service1();
DataSet MyChangedRows;
dataGrid1.DataMember = "";
dataGrid1.DataSource = null;
//Pull out only what you must send over the wire.
MyChangedRows = ds.GetChanges();
MyChangedRows = sv.UpdateData(MyChangedRows);
//You must accept changes on the DataSet because of a known problem. See Q313540.
ds.AcceptChanges();
ds.EnforceConstraints = false;
//Merge in the parent rows first and then the child rows.
ds.Merge(MyChangedRows.Tables["Orders"], false, MissingSchemaAction.Ignore);
ds.Merge(MyChangedRows.Tables["details"], false, MissingSchemaAction.Ignore);
//Accept changes that you have made to the DataSet.
ds.AcceptChanges();
//Turn on the integrity constraints that you turned off earlier.
ds.EnforceConstraints = true;
dataGrid1.DataSource = ds;
dataGrid1.DataMember = "Orders";
Pressione F5 para compilar e executar o aplicativo cliente.
Na dataGrid1 , modifique alguns dos dados e, em seguida, clique em Salvar .
Observação : não alterar o campo de chave. Se você alterar o campo de chave, você receber uma mensagem de erro, que declara que são significativas integridade referencial no servidor.
Adicione uma linha filho a uma linha pai existente. Observe que a linha filho recebe automaticamente o valor correto da chave estrangeira.
Adicione os seguintes valores para uma nova linha pai e uma nova linha filho e, em seguida, clique em Salvar . Observe os seguintes valores de chave:
Para obter informações adicionais, clique nos números abaixo para ler os artigos na Base de dados de Conhecimento da Microsoft:
310143
(http://support.microsoft.com/kb/310143/EN-US/
)
COMO: Atualizar dados do servidor por meio de uma Web Service usando o ADO.NET e Visual translation from VPE for Csharp .NET
313483
(http://support.microsoft.com/kb/313483/EN-US/
)
INFO: Guia para objetos de DataAdapter do ADO.NET
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 320301
(http://support.microsoft.com/kb/320301/en-us/
)
Quanto esforço foi necessário para seguir os procedimentos deste artigo?
Muito baixo
Baixo
Moderado
Alto
Muito alto
Diga-nos o porque e o que podemos fazer para melhorar esta informação
Obrigado! Seus comentários são usados para nos ajudar a aperfeiçoar o conteúdo de suporte. Para obter mais opções de ajuda, visite a Home Page de Ajuda e Suporte.