Artigo: 320301 - Última revisão: domingo, 1 de Fevereiro de 2004 - Revisão: 3.4
COMO: Actualizar dados de ascendente-subordinado com uma coluna de identidade a partir de uma aplicação de formulários do Windows utilizando um Web Service no Visual C# .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 obter um objecto de DataSet a partir de um serviço Web, como enviar DiffGram actualizações para o serviço da Web e, em seguida, como intercalar DiffGram actualizado novamente o cliente DataSet . Este processo envolve os seguintes passos:
A aplicação cliente obtém um objecto de DataSet com dois objectos de DataTable numa relação principal-subordinado do serviço Web. O DataTable principal tem uma coluna de identidade/numeração automática como chave primária.
Na aplicação cliente, o utilizador pode adicionar, eliminar e modificar registos principal e subordinado registos. Novos registos principal recebem um temporário valor chave primária que é gerado localmente.
A aplicação cliente envia alterações para a Web serviço como um DiffGram.
O serviço Web actualiza a base de dados, obtém reais valores de chave primária para novos registos principal e, em seguida, propaga valores da chave são alterados para registos subordinados.
A aplicação cliente recebe os valores actualizados do serviço Web e, em seguida, intercala os valores actualizados para o local DataSet .
Para obter informações adicionais sobre como actualizar uma única tabela utilizando um serviço Web, clique no número de artigo existente abaixo para visualizar o artigo na base de dados de conhecimento da Microsoft:
310143
(http://support.microsoft.com/kb/310143/EN-US/
)
COMO: O serviço de actualização de dados do servidor através de uma Web utilizando o ADO.NET e Visual C# .NET
A lista seguinte 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 está familiarizado com os seguintes tópicos:
Visual Studio .NET
Noções básicas do ADO.NET e sintaxe
Noções básicas ASP.NET e sintaxe
Os exemplos de código neste artigo utilizam http://localhost como o servidor Web. Além disso, os exemplos de código utilizam a base de dados Adamastor da base de dados. A base de dados Adamastor, incluída no Microsoft SQL Server.
Para criar um novo projecto do Visual C# ASP.NET Web Service, siga estes passos:
Inicie o Visual Studio NET..
No menu ficheiro , aponte para Novo e, em seguida, clique em projecto .
Clique em Visual C# Projects em Project Types e, em seguida, clique em Serviço Web do ASP.NET em modelos .
Na caixa localização , a localização predefinida é apresentada como http://localhost/WebService1. Escreva o URL do servidor (por exemplo, http://localhost executa serviço da Web no servidor Web local). Substituir WebService1 com CSharpUpdateData . O URL na caixa localização deverá aparecer da seguinte forma:
http://localhost/CSharpUpdateData
Para fechar a caixa de diálogo Novo projecto , clique em OK .
No Service1.asmx.cs[Design] página, mude para vista de código. Repare que aparece a janela código para o serviço Web.
Na parte superior da janela de código, adicione a seguinte instrução utilizando :
using System.Data.SqlClient;
Adicione o seguinte para a implementação de 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 cadeias SqlConnection ligar ao servidor que esteja a executar o SQL Server.
Prima F5 para compilar e executar o serviço Web. Repare que é devolvida uma página Web com o URL http://localhost/CSharpUpdateData/Service1.asmx. Nesta página Web, pode interagir com o serviço Web a partir do Microsoft Internet Explorer.
Na página Web Service1.asmx, clique em GetData . Repare que é devolvida uma página Web que apresenta os detalhes acerca do método GetData Web.
Para criar um novo projecto de aplicação do Windows do Visual C#, siga estes passos:
No menu ficheiro do Visual Studio. NET, aponte para Novo e, em seguida, clique em projecto .
Na caixa de diálogo Novo projecto , clique em Visual C# Projects em Project Types e, em seguida, clique em Aplicação do Windows em modelos . Por predefinição, o Form1 é adicionada ao projecto.
Arraste um controlo de botão e o controlo DataGrid da caixa de ferramentas ao Form1. Por predefinição, os controlos são denominados button1 e dataGrid1 respectivamente.
Altere a propriedade Name do button1 para btnSave e, em seguida, altere a propriedade texto de button1 para Guardar .
No menu projecto , clique em ' Adicionar referência Web '. Escreva o URL para o serviço Web (neste caso, tipo http://localhost/CSharpUpdateData/Service1.asmx ), prima ENTER e, em seguida, clique em Add Reference . Repare que a entrada para esta referência Web é apresentada no Solution Explorer.
Adicione o seguinte código à classe Form1 para declarar um membro de nível do formulário para DataSet :
private System.Data.DataSet ds;
Faça duplo clique no formulário para mudar para vista de código e repare que o Visual Studio .NET cria o método Form1_Load . Adicione o seguinte código para o método Form1_Load :
Abra a janela código para o botão Guardar e, em seguida, adicione o seguinte código ao processador de eventos 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";
Prima F5 para compilar e executar a aplicação cliente.
Na dataGrid1 , modificar alguns dos dados e, em seguida, clique em Guardar .
Nota : não altere o campo de chave. Se alterar o campo chave, receberá uma mensagem de erro que indica que está a separar a integridade referencial no servidor.
Adicione uma linha subordinada a uma linha principal existente. Repare que a linha subordinada recebe automaticamente o valor de chave externo correcto.
Adicione os seguintes valores para uma nova linha principal e uma nova linha subordinada e, em seguida, clique em Guardar . Tenha em atenção os seguintes valores chaves:
Para obter informações adicionais, clique nos números de artigo existentes abaixo para visualizar os artigos na Microsoft Knowledge Base:
310143
(http://support.microsoft.com/kb/310143/EN-US/
)
COMO: O serviço de actualização de dados do servidor através de uma Web utilizando o ADO.NET e Visual C# .NET
313483
(http://support.microsoft.com/kb/313483/EN-US/
)
INFO: Guia para objectos de ' DataAdapter ' 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 revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes 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/
)
Qual foi o esforço que despendeu pessoalmente para utilizar este artigo?
Muito baixo
Baixo
Moderado
Elevado
Muito elevado
Diga-nos porquê e o que podemos fazer para melhorar estas informações
Obrigado! Os seus comentários são utilizados para ajudar-nos a melhorar o conteúdo do nosso suporte. Para obter mais opções de assistência, visite a Home Page de Ajuda e Suporte.