ПРАКТИЧЕСКОЕ руководство: Обновление родительских и дочерних данных со столбцом идентификаторов из приложения Windows Forms с помощью веб-службы в Visual C#.NET
Эта статья содержит пошаговые инструкции для извлечения Набор данных Объект, расположенный на веб-службы, как отправить обновления DiffGram
Веб-службы, а затем объединить DiffGram обновленный клиент Набор данных. Этот процесс включает следующие шаги:
Получение клиентского приложения Набор данных объект с двумя Объект DataTable объекты в отношении родительский дочерний веб-службы. В
родители Объект DataTable содержит столбец Identity или Autonumber как первичный ключ.
В клиентском приложении пользователь может добавлять, удалять и
Изменение родительских и дочерних записей. Новые записи родительского получать временный
значение первичного ключа, созданного локально.
Клиентское приложение отправляет изменения обратно в Интернете
Служба в формате DiffGram.
Обновляет базу данных, веб-службы, извлекает фактический
первичный ключ значения для новых родительских записей и затем передает значения ключей
изменения дочерних записей.
Клиентское приложение получает обновленные значения из
Веб-службы, а затем объединяет обновленные значения обратно в локальный Набор данных.
Для получения дополнительных сведений об обновлении одной таблицы
с помощью веб-службы, щелкните следующий номер статьи для просмотра статьи в
в Microsoft Knowledge Base:
ПРАКТИЧЕСКОЕ руководство: Обновление данных сервера веб-службы с помощью ADO.NET и Visual C#.NET
Требования
В следующем списке представлены рекомендуемого оборудования, программного обеспечения,
сетевой инфраструктуры и пакетов обновления, которые необходимы:
Microsoft Windows 2000 Professional, Windows 2000 Server
Windows 2000 Advanced Server или Windows NT 4.0 Server
Microsoft Visual Studio.NET
В данной статье предполагается, что вы знакомы со следующими
разделы:
Visual Studio.NET
ADO.NET основы и синтаксис
ASP.NET основы и синтаксис
Примеры кода в этой статье используют http://localhost как
Веб-сервер. Кроме того, с помощью примеров кода «Борей» базы данных в качестве базы данных. В «Борей» База данных входит в состав Microsoft SQL Server.
Создание веб-службы
Чтобы создать новый Visual C# ASP.NET веб-службы проекта
выполните следующие действия.
Запустите Visual Studio.NET.
На Файл Выберите пункт Новый, а затем нажмите кнопку Проект.
Нажмите кнопку Проекты Visual C# Из списка Типы проектов, а затем нажмите кнопку ASP.NET веб-службы Из списка Шаблоны.
В Расположение поле, по умолчанию отображается в виде
http://localhost/WebService1. Введите URL-адрес сервера (например,
адрес http://localhost запускает веб-службы на локальном веб-сервере). Замена
WebService1 с CSharpUpdateData. URL-адрес в Расположение поле должно выглядеть следующим образом:
http://localhost/CSharpUpdateData
Чтобы закрыть Новый проект диалоговое окно, нажмите кнопку ОК.
На Service1.asmx.cs[Design] страницы, переключитесь в представление «код».
Обратите внимание, что открывается окно кода для веб-службы.
В верхней части окна кода добавьте следующую с помощью инструкции:
using System.Data.SqlClient;
Добавьте в класс 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;
}
Измените строки SqlConnection для подключения к серверу
на котором запущен SQL Server.
Тестирование веб-службы
Нажмите клавишу F5 для компиляции и запуска веб-службы. Обратите внимание, что
веб-страницы возвращается с URL-адреса
http://localhost/CSharpUpdateData/Service1.asmx. В этой веб-страницы можно
взаимодействие с веб-службы в обозревателе Internet Explorer.
Service1.asmx веб-страницы нажмите кнопку GetData. Обратите внимание, что возвращаемый веб-страницы, отображающей подробные сведения о
очередь GetData Веб-метода.
Закройте веб-страниц.
Создание клиентского приложения
Создание нового проекта приложения Windows Visual C#
выполните следующие действия.
На Файл меню Visual Studio.NET, выберите пункт Новый, а затем нажмите кнопку Проект.
В Новый проект диалоговое окно, нажмите кнопку Проекты Visual C# Из списка Типы проектов, а затем нажмите кнопку Приложение Windows Из списка Шаблоны. По умолчанию Form1 добавляется в проект.
Перетаскивание Кнопка элемент управления и DataGrid элемент управления из панели элементов в форму Form1. По умолчанию, элементы управления
с именем Button1 и dataGrid1 соответственно.
Изменение Имя свойства элемента Button1 Кому btnSave, а затем измените Текст свойства элемента Button1 Кому Сохранить.
На Проект меню, нажмите кнопку Добавление веб-ссылки. Введите URL-адрес для веб-службы (в данном случае типhttp://localhost/CSharpUpdateData/Service1.asmx), нажмите клавишу
Введите, а затем нажмите кнопку Добавить ссылку. Обратите внимание, что в решении появится запись для этого веб-ссылки
Обозреватель.
Добавьте следующий код в класс Form1 для объявления
член на уровне формы для Набор данных:
private System.Data.DataSet ds;
Дважды щелкните форму, чтобы перейти в представление «код» и обратите внимание
Visual Studio.NET создает Form1_Load метод. Добавьте следующий код для Form1_Load метод:
Откройте окно программного кода Сохранить Кнопка, а затем добавьте следующий код для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";
Тестирование клиентского приложения
Нажмите клавишу F5 для компиляции и запуска клиента
приложения.
В dataGrid1, изменить некоторые данные и нажмите кнопку Сохранить.
ПРИМЕЧАНИЕ: Не изменяйте поле ключа. При изменении поля ключа,
появляется сообщение об ошибке, говорится, что разбиении ссылок
целостность на сервере.
Добавление дочерней строки к существующей родительской строки. Обратите внимание, что
Дочерняя строка автоматически получает правильные значения внешнего ключа.
Добавьте следующие параметры для новой родительской строки и новый
дочерние строки, а затем нажмите Сохранить. Обратите внимание на следующие ключевые значения:
ВНИМАНИЕ! Перевод данной статьи был выполнен не человеком, а с помощью программы машинного перевода, разработанной корпорацией Майкрософт. Корпорация Майкрософт предлагает вам статьи, переведенные как людьми, так и средствами машинного перевода, чтобы у вас была возможность ознакомиться со статьями базы знаний KB на родном языке. Однако машинный перевод не всегда идеален. Он может содержать смысловые, синтаксические и грамматические ошибки, подобно тому как иностранец делает ошибки, пытаясь говорить на вашем языке. Корпорация Майкрософт не несет ответственности за неточности, ошибки и возможный ущерб, причиненный в результате неправильного перевода или его использования. Корпорация Майкрософт также часто обновляет средства машинного перевода.
Спасибо! Благодаря вашему отзыву мы сможем сделать справочные материалы еще лучше. Чтобы воспользоваться дополнительными возможностями поддержки, посетите домашнюю страницу центра справки и поддержки.