ПРАКТИЧЕСКОЕ руководство: Обновление родительских и дочерних данных со столбцом идентификаторов из приложения Windows Forms с помощью веб-службы в Visual C#.NET

Код статьи: 320301 - Список продуктов, к которым относится данная статья.
Развернуть все | Свернуть все

На этой странице

Аннотация

Эта статья содержит пошаговые инструкции для извлечения Набор данных Объект, расположенный на веб-службы, как отправить обновления DiffGram Веб-службы, а затем объединить DiffGram обновленный клиент Набор данных. Этот процесс включает следующие шаги:
  1. Получение клиентского приложения Набор данных объект с двумя Объект DataTable объекты в отношении родительский дочерний веб-службы. В родители Объект DataTable содержит столбец Identity или Autonumber как первичный ключ.
  2. В клиентском приложении пользователь может добавлять, удалять и Изменение родительских и дочерних записей. Новые записи родительского получать временный значение первичного ключа, созданного локально.
  3. Клиентское приложение отправляет изменения обратно в Интернете Служба в формате DiffGram.
  4. Обновляет базу данных, веб-службы, извлекает фактический первичный ключ значения для новых родительских записей и затем передает значения ключей изменения дочерних записей.
  5. Клиентское приложение получает обновленные значения из Веб-службы, а затем объединяет обновленные значения обратно в локальный Набор данных.
Для получения дополнительных сведений об обновлении одной таблицы с помощью веб-службы, щелкните следующий номер статьи для просмотра статьи в в Microsoft Knowledge Base:
310143 ПРАКТИЧЕСКОЕ руководство: Обновление данных сервера веб-службы с помощью 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.

Создание веб-службы

  1. Чтобы создать новый Visual C# ASP.NET веб-службы проекта выполните следующие действия.
    1. Запустите Visual Studio.NET.
    2. На Файл Выберите пункт Новый, а затем нажмите кнопку Проект.
    3. Нажмите кнопку Проекты Visual C# Из списка Типы проектов, а затем нажмите кнопку ASP.NET веб-службы Из списка Шаблоны.
    4. В Расположение поле, по умолчанию отображается в виде http://localhost/WebService1. Введите URL-адрес сервера (например, адрес http://localhost запускает веб-службы на локальном веб-сервере). Замена WebService1 с CSharpUpdateData. URL-адрес в Расположение поле должно выглядеть следующим образом:
      http://localhost/CSharpUpdateData
    5. Чтобы закрыть Новый проект диалоговое окно, нажмите кнопку ОК.
  2. На Service1.asmx.cs[Design] страницы, переключитесь в представление «код». Обратите внимание, что открывается окно кода для веб-службы.
  3. В верхней части окна кода добавьте следующую с помощью инструкции:
    using System.Data.SqlClient;
  4. Добавьте в класс 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;
    						
    
            } 
    					
  5. Измените строки SqlConnection для подключения к серверу на котором запущен SQL Server.

Тестирование веб-службы

  1. Нажмите клавишу F5 для компиляции и запуска веб-службы. Обратите внимание, что веб-страницы возвращается с URL-адреса http://localhost/CSharpUpdateData/Service1.asmx. В этой веб-страницы можно взаимодействие с веб-службы в обозревателе Internet Explorer.
  2. Service1.asmx веб-страницы нажмите кнопку GetData. Обратите внимание, что возвращаемый веб-страницы, отображающей подробные сведения о очередь GetData Веб-метода.
  3. Закройте веб-страниц.

Создание клиентского приложения

  1. Создание нового проекта приложения Windows Visual C# выполните следующие действия.
    1. На Файл меню Visual Studio.NET, выберите пункт Новый, а затем нажмите кнопку Проект.
    2. В Новый проект диалоговое окно, нажмите кнопку Проекты Visual C# Из списка Типы проектов, а затем нажмите кнопку Приложение Windows Из списка Шаблоны. По умолчанию Form1 добавляется в проект.
  2. Перетаскивание Кнопка элемент управления и DataGrid элемент управления из панели элементов в форму Form1. По умолчанию, элементы управления с именем Button1 и dataGrid1 соответственно.
  3. Изменение Имя свойства элемента Button1 Кому btnSave, а затем измените Текст свойства элемента Button1 Кому Сохранить.
  4. На Проект меню, нажмите кнопку Добавление веб-ссылки. Введите URL-адрес для веб-службы (в данном случае типhttp://localhost/CSharpUpdateData/Service1.asmx), нажмите клавишу Введите, а затем нажмите кнопку Добавить ссылку. Обратите внимание, что в решении появится запись для этого веб-ссылки Обозреватель.
  5. Добавьте следующий код в класс Form1 для объявления член на уровне формы для Набор данных:
           private System.Data.DataSet ds;
    					
  6. Дважды щелкните форму, чтобы перейти в представление «код» и обратите внимание Visual Studio.NET создает Form1_Load метод. Добавьте следующий код для Form1_Load метод:
        localhost.Service1 sv = new localhost.Service1();
        ds = sv.GetData ();
           
        dataGrid1.DataSource = ds;
        dataGrid1.DataMember = "Orders";
    					
  7. Переключитесь в режим формы.
  8. Откройте окно программного кода Сохранить Кнопка, а затем добавьте следующий код для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";
    					

Тестирование клиентского приложения

  1. Нажмите клавишу F5 для компиляции и запуска клиента приложения.
  2. В dataGrid1, изменить некоторые данные и нажмите кнопку Сохранить.

    ПРИМЕЧАНИЕ: Не изменяйте поле ключа. При изменении поля ключа, появляется сообщение об ошибке, говорится, что разбиении ссылок целостность на сервере.
  3. Добавление дочерней строки к существующей родительской строки. Обратите внимание, что Дочерняя строка автоматически получает правильные значения внешнего ключа.
  4. Добавьте следующие параметры для новой родительской строки и новый дочерние строки, а затем нажмите Сохранить. Обратите внимание на следующие ключевые значения:
    • Orders.CustomerID=RATTC
    • Orders.EmployeeID=1
    • Orders.OrderDate=2/2/2002
    • Details.ProductID=1
    • Details.UnitPrice=18
    • Details.Quantity=1
    • Details.Discount=0

Ссылки

Для дополнительной сведения, щелкните следующий номер статьи для просмотра статьи в База знаний корпорации Майкрософт:
310143 ПРАКТИЧЕСКОЕ руководство: Обновление данных сервера веб-службы с помощью ADO.NET и Visual C#.NET
313483 ИНФОРМАЦИЯ: Путеводитель для ADO.NET DataAdapter объектов

Свойства

Код статьи: 320301 - Последнее изменение :: 8 июня 2011 г. - Редакция: 4.0
Информация в данной статье относится к следующим продуктам.
  • Microsoft Visual C# .NET 2003 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
  • Microsoft ADO.NET 1.1
  • Microsoft ASP.NET 1.1
  • Microsoft ASP.NET 1.0
Ключевые слова: 
kbdatabinding kbhowtomaster kbsqlclient kbsystemdata kbmt KB320301 KbMtru
Переведено с помощью машинного перевода
ВНИМАНИЕ! Перевод данной статьи был выполнен не человеком, а с помощью программы машинного перевода, разработанной корпорацией Майкрософт. Корпорация Майкрософт предлагает вам статьи, переведенные как людьми, так и средствами машинного перевода, чтобы у вас была возможность ознакомиться со статьями базы знаний KB на родном языке. Однако машинный перевод не всегда идеален. Он может содержать смысловые, синтаксические и грамматические ошибки, подобно тому как иностранец делает ошибки, пытаясь говорить на вашем языке. Корпорация Майкрософт не несет ответственности за неточности, ошибки и возможный ущерб, причиненный в результате неправильного перевода или его использования. Корпорация Майкрософт также часто обновляет средства машинного перевода.
Эта статья на английском языке:320301

Отправить отзыв