데이터 삽입 방법(ADO.NET 데이터 서비스/Silverlight)
System.Data.Services.Client 라이브러리를 사용하는 Silverlight 응용 프로그램에서는 ADO.NET 데이터 서비스에 데이터를 삽입할 수 있습니다. 이 단원의 코드 시나리오에서는 데이터 모델 및 데이터 서비스 구현(ADO.NET 데이터 서비스/Silverlight)에 설명되어 있는 데이터 서비스를 사용합니다. 이 항목에서는 클라이언트 응용 프로그램이 사용자 지정 항목을 System.Data.Services.Client..::.DataServiceContext의 로컬 인스턴스에 추가하여 Northwind 데이터 서비스의 저장소에 유지하는 방법을 보여 줍니다.
이 예제의 쿼리는 LINQ 구문을 사용하며 미국 지역 고객을 식별하는 where 절을 포함합니다. 비동기 메서드는 서비스에서 데이터를 가져와서 Customer 형식의 ObservableCollection<T>으로 읽어 옵니다. 이 컬렉션은 데이터 표의 DataServiceContext에 할당됩니다.
Silverlight 응용 프로그램
Silverlight 응용 프로그램을 구현하려면
-
데이터 모델 및 데이터 서비스 구현(ADO.NET 데이터 서비스/Silverlight)에 설명되어 있는 ASP.NET 웹 응용 프로그램을 만들거나 다시 사용합니다.
-
Visual Studio 솔루션 탐색기에서 솔루션을 마우스 오른쪽 단추로 클릭하고 추가를 가리킨 다음 새 항목을 선택합니다.
-
새 항목 추가 대화 상자에서 Silverlight 범주의 새 프로젝트를 추가합니다. 프로젝트 이름을 SilverlightClientApp2로 지정합니다.
-
Silverlight 응용 프로그램 추가 대화 상자에서 Silverlight 컨트롤을 기존 웹 사이트에 연결, 응용 프로그램을 참조하는 테스트 페이지 추가 및 시작 페이지로 만들기를 선택합니다.
-
ASP.NET 웹 응용 프로그램 속성 페이지에서 웹/시작 작업 섹션에 특정 페이지가 선택되어 있는지 확인합니다. 새 프로젝트의 *.html 테스트 페이지를 사용합니다. 그러면 텍스트 상자에 Silverlight 응용 프로그램 HTML 테스트 페이지가 시작 페이지로 표시됩니다.
중요:
ADO.NET 데이터 서비스의 Silverlight 클라이언트는 데이터 서비스 호스트와 동일한 도메인에 있어야 합니다. 예를 들어 클라이언트 응용 프로그램이 http://domain-x/SilverlightApp.html에 있는 경우 http://domain-x/dataservice.svc로 데이터 서비스 요청을 보내면 클라이언트와 데이터 서비스가 같은 도메인에 있으므로 요청이 성공합니다. 도메인 x에 있는 클라이언트 응용 프로그램에서 http://domain-z/dataservice.svc로 요청을 보내면 대상 데이터 서비스가 다른 도메인에 있으므로 요청이 실패합니다.
Silverlight 사용자 인터페이스
이 예제의 사용자 인터페이스에는 System.Windows.Controls.Data 어셈블리의 DataGrid 컨트롤과 StackPanel이 포함됩니다. 데이터 표에서는 Silverlight용 클라이언트 응용 프로그램(ADO.NET 데이터 서비스/Silverlight)에 구현된 것과 유사한 데이터 바인딩 시나리오를 사용하여 데이터를 표시합니다. 이전 예제의 목록 상자와는 달리 데이터 표에 바인딩할 때 페이지 스키마에 데이터 템플릿을 정의하지 않아도 됩니다.
사용자 인터페이스를 구현하려면
-
프로젝트에 System.Windows.Controls.Data에 대한 참조를 추가합니다.
-
클라이언트 응용 프로그램의 Page.xaml 파일에 xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" xmlns 참조를 추가합니다.
-
UserControl 블록은 다음과 같습니다.
<UserControl x:Class="SilverlightClientApp2.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" Width="800" Height="400">
-
다음과 같이 Page.xaml 파일의 Grid 요소에 RowDefinitions를 추가합니다.
<Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="4*"/> </Grid.RowDefinitions> </Grid>
-
Grid에 StackPanel을 추가합니다.
<StackPanel Orientation="Horizontal"> </StackPanel>
-
다음 XML 예제에 표시된 것과 같이 StackPanel에 단추와 텍스트 상자를 추가합니다. 텍스트 상자에는 새 Customer에 대한 데이터를 입력할 수 있습니다. Get Data 단추와 Insert 단추에 Click을 할당하면 이 사용자 인터페이스의 코드에서 처리기 메서드가 해당 단추에 할당됩니다.
<StackPanel Orientation="Horizontal"> <Button Content="Get Data" Width="75" Height="20" Margin="10" Click="OnGetData"/> <Button Content="Insert" Width="75" Height="20" Margin="10" Click="OnInserted"/> <TextBox Text="IDXXX" Width="75" Height="25" Margin="10" Name="textBoxCustomerID"/> <TextBox Text="CompanyName" Width="75" Height="25" Margin="10" Name="textBoxCompanyName"/> </StackPanel>
-
System.Windows.Controls.Data 어셈블리에서 DataGrid 컨트롤을 추가합니다. Northwind 데이터를 표시할 수 있도록 ItemsSource 특성을 {Binding}으로 설정합니다.
<data:DataGrid Name="dataGrid1" Grid.Row="1" Margin="20" AutoGenerateColumns="True" ItemsSource="{Binding}" > </data:DataGrid>
다음은 완성된 Page.xaml 파일입니다.
<UserControl x:Class="SilverlightClientApp2.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" Width="800" Height="400"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> <RowDefinition Height="4*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <Button Content="Get Data" Width="75" Height="20" Margin="10" Click="OnGetData"/> <Button Content="Insert" Width="75" Height="20" Margin="10" Click="OnInserted"/> <TextBox Text="IDXXX" Width="75" Height="25" Margin="10" Name="textBoxCustomerID"/> <TextBox Text="CompanyName" Width="75" Height="25" Margin="10" Name="textBoxCompanyName"/> </StackPanel> <TextBlock x:Name="CustomerBlock" Grid.Row="1" Text="Customers:" Grid.Column="0" FontFamily="Calibri"/> <data:DataGrid Name="dataGrid1" Grid.Row="2" Margin="10" AutoGenerateColumns="True" ItemsSource="{Binding}" > </data:DataGrid> <TextBlock x:Name="textBlock" Grid.Row="3" Text="" Grid.Column="0" FontFamily="Calibri"/> </Grid> </UserControl>
데이터 표시 및 삽입을 위한 클라이언트 코드
사용자 인터페이스에서 dataGrid1의 ItemsSource는 데이터 바인딩을 지정합니다. ADO.NET 데이터 서비스에 대한 데이터 바인딩을 사용하려면 클라이언트 메서드에서 데이터 서비스의 응답을 기다려야 하므로 비동기 메서드를 사용해야 합니다.
데이터 바인딩 및 표시
Northwind 데이터 서비스에서 Customer 데이터를 가져오고 표시하려면
-
참조를 추가하거나, Silverlight 프로젝트에서 다음 어셈블리를 참조하는지 확인한 후 이러한 어셈블리에 대한 using 지시문을 Page.xaml.cs 파일에 추가합니다.
using System.Data.Services.Client; using System.Collections.ObjectModel;
-
데이터 서비스 클래스에 대한 using 지시문을 Page.xaml.cs 파일에 추가합니다.
using SilverlightClientApp2.NorthwindSvc;
-
다음 코드 예제와 같이 페이지 초기화 코드를 구현합니다. NorthwindEntities 클래스는 이 응용 프로그램에서 사용하는 DataServiceContext 클래스를 구현한 것입니다. 다음 코드를 사용하면 Silverlight 페이지가 로드될 때 DataServiceContext가 초기화됩니다. 6단계에 설명된 것처럼 데이터 바인딩에는 Customer 형식의 ObservableCollection<T>이 사용됩니다.
namespace SilverlightClientApp2 { public partial class Page : UserControl { NorthwindEntities svcContext; ObservableCollection<Customer> obsvCollCustomers; public Page() { InitializeComponent(); this.Loaded += OnLoaded; } void OnLoaded(object sender, EventArgs args) { svcContext = new NorthwindEntities( new Uri("Northwind.svc", UriKind.Relative)); obsvCollCustomers = new ObservableCollection<Customer>(); }
-
다음 코드와 같이 Get Data 단추의 Click 메서드에 지정된 메서드를 구현합니다. Customer 형식의 DataServiceQuery<(Of <(TElement>)>)을 만듭니다. 이 예제에서는 where 절과 select 문이 포함된 LINQ 구문을 사용합니다. 쿼리를 정의한 후에는 비동기 메서드 BeginExecute를 호출합니다. 메서드의 첫 번째 매개 변수는 데이터 서비스에서 결과를 반환할 때 쿼리를 완료할 콜백 함수를 식별합니다.
void OnGetData(object sender, EventArgs args) { DataServiceQuery<Customer> query = (DataServiceQuery<Customer>) (from c in svcContext.Customers where c.Country == "USA" select c); query.BeginExecute(GetDataCallback, query); }
-
이전 단계에서 시작된 쿼리의 결과를 처리하는 콜백 함수를 구현합니다. 비동기 작업의 결과는 결과 매개 변수에 포함된 IAsyncResult.AsyncState 개체에 들어 있습니다. AsyncState를 Customer 형식의 DataServiceQuery<(Of <(TElement>)>)로 캐스팅하여 쿼리 결과를 열거합니다.
-
Customer 형식의 ObservableCollection<T>을 초기화합니다. 이 클래스는 변경 사항이 발생했을 때 알림을 보내기 때문에 데이터 바인딩에 사용됩니다. 이 방법은 데이터 변경 사항을 데이터 서비스에 저장한 후에 비동기 메서드에서 반환하는 경우 유용합니다. 쿼리 결과를 처리하는 스레드에서 사용자 인터페이스 스레드에 대해 프로시저를 호출하려면 Dispatcher 개체가 필요합니다. Dispatcher 대괄호 안에서 호출되는 코드는 고객의 ObservableCollection을 dataGrid1의 DataContext 속성에 할당합니다.
void GetDataCallback(IAsyncResult result) { try { DataServiceQuery<Customer> queryResult = (DataServiceQuery<Customer>) result.AsyncState; IEnumerable<Customer> results = queryResult.EndExecute(result); foreach (var item in results) obsvCollCustomers.Add(item); Dispatcher.BeginInvoke(() => { dataGrid1.DataContext = obsvCollCustomers; }); } catch (DataServiceRequestException ex) { textBlock.Text = "Error: " + ex.Response.ToString(); } }
-
응용 프로그램을 빌드하고 실행합니다. Get Data 단추를 클릭하면 페이지의 데이터 표가 Northwind 데이터 서비스에서 가져온 고객으로 채워집니다.
데이터 삽입
Silverlight 사용자 인터페이스에서 Customer 데이터 형식의 새 인스턴스를 만들어 데이터 서비스에 삽입하려면
-
Insert 단추의 Click 메서드에 지정된 OnInserted 메서드를 구현합니다. OnInserted 메서드는 Customer 데이터 형식의 새 인스턴스를 만든 다음 페이지의 텍스트 상자에 있는 데이터로부터 null을 허용하지 않는 CustomerID 및 CompanyName 속성을 할당합니다. OnGetData에서 DataServiceQuery<(Of <(TElement>)>)의 where 절은 Country == USA인 결과를 지정하므로 Country 속성을 할당합니다. 그런 다음에는 컨트롤에 표시되는 데이터에 새 항목을 표시하기 원할 수 있습니다. 모든 할당 작업이 완료되면 Northwind 서비스의 DataServiceContext를 사용하여 새 Customer를 추가합니다. 클라이언트 클래스에서 제공하는 AddToCustomers 메서드를 호출하여 Customer를 추가합니다. 그런 다음 콜백 함수와 새 Customer 인스턴스를 식별하는 매개 변수를 사용하여 System.Data.Services.Client 라이브러리에서 BeginSaveChanges 메서드를 호출합니다.
void OnInserted(object sender, EventArgs args) { Customer newCustomer = new Customer(); newCustomer.CustomerID = textBoxCustomerID.Text; newCustomer.CompanyName = textBoxCompanyName.Text; newCustomer.Country = "USA"; svcContext.AddToCustomers(newCustomer); svcContext.BeginSaveChanges(OnSaveChangesCompleted, newCustomer); }
-
OnSaveChangesCompleted를 구현하여 이전 단계에서 호출한 BeginSaveChanges의 비동기 결과를 처리합니다. 콜백 함수는 DataServiceContext의 EndSaveChanges 멤버를 사용하여 Northwind svcContext를 통해 데이터 서비스의 데이터를 업데이트합니다. IAsyncResultObservableCollection 개체를 Customer 형식으로 캐스팅하여 ObservableCollection ObsvCollCustomers에 추가할 수 있습니다. 이렇게 하면 데이터 표가 자동으로 업데이트됩니다.
void OnSaveChangesCompleted(IAsyncResult result) { try { proxy.EndSaveChanges(result); // Add the new customer to the grid. obsvCollCustomers.Add(result.AsyncState as Customer); textBlock.Text = "Insert complete: " + (result.AsyncState as Customer).CustomerID; } catch (DataServiceRequestException ex) { textBlock.Text = "OnSaveChangesCompleted Error: " + ex.Response.ToString(); } }
응용 프로그램을 실행합니다. IDXXX 텍스트 상자에 다섯 자로 된 고객 ID를 입력하고 CompanyName 텍스트 상자에 회사 이름을 입력합니다. Insert 단추를 클릭하여 새 고객을 추가하고, 새 항목이 포함된 결과로 데이터 표를 업데이트합니다.
다음 코드에서는 이 항목에서 사용된 Page.xaml.cs 파일의 전체 콘텐츠를 보여 줍니다.
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Data.Services.Client; using System.Collections.ObjectModel; using SilverlightClientApp2.NorthwindSvc; namespace SilverlightClientApp2 { public partial class Page : UserControl { NorthwindEntities proxy; ObservableCollection<Customer> obsvCollCustomers; public Page() { InitializeComponent(); this.Loaded += OnLoaded; } void OnLoaded(object sender, EventArgs args) { proxy = new NorthwindEntities( new Uri("Northwind.svc", UriKind.Relative)); obsvCollCustomers = new ObservableCollection<Customer>(); } void OnGetData(object sender, EventArgs args) { DataServiceQuery<Customer> query = (DataServiceQuery<Customer>) (from c in proxy.Customers where c.Country == "USA" select c); query.BeginExecute(GetDataCallback, query); } void GetDataCallback(IAsyncResult result) { try { DataServiceQuery<Customer> queryResult = (DataServiceQuery<Customer>)result.AsyncState; IEnumerable<Customer> results = queryResult.EndExecute(result); foreach (var item in results) obsvCollCustomers.Add(item); Dispatcher.BeginInvoke(() => { dataGrid1.DataContext = obsvCollCustomers; }); } catch(DataServiceRequestException ex) { ex.Response.ToString(); } } void OnInserted(object sender, EventArgs args) { Customer newCustomer = new Customer(); newCustomer.CustomerID = textBoxCustomerID.Text; newCustomer.CompanyName = textBoxCompanyName.Text; newCustomer.Country = "USA"; proxy.AddToCustomers(newCustomer); proxy.BeginSaveChanges(OnSaveChangesCompleted, newCustomer); } void OnSaveChangesCompleted(IAsyncResult result) { try { proxy.EndSaveChanges(result); obsvCollCustomers.Add(result.AsyncState as Customer); textBlock.Text = "Insert complete: " + (result.AsyncState as Customer).CustomerID; } catch (DataServiceRequestException ex) { textBlock.Text = "OnSaveChangesCompleted Error: " + ex.Response.ToString(); } } } }
System.Data.Services.Client 라이브러리를 사용하는 Silverlight용 응용 프로그램에서는 ADO.NET 데이터 서비스에서 배포되는 데이터를 업데이트 및 삭제할 수 있습니다. 이 항목의 코드는 데이터 삽입 방법(ADO.NET 데이터 서비스/Silverlight) 항목에서 설명한 시나리오를 확장하고 이전 예제에 구현된 ASP.NET 웹 응용 프로그램을 사용합니다.
데이터를 업데이트 및 삭제하는 클라이언트 코드
데이터를 업데이트할 때는 이전 예제에 표시된 것과 비슷한 동기화 메서드를 사용합니다. 다음 예제에서는 Category 데이터 형식을 사용하여 업데이트 및 삭제 절차를 설명합니다. Category 데이터 형식은 Product 데이터에만 연결됩니다.
참고:
데이터를 업데이트할 때는 데이터 모델을 분석하여 연결이 제대로 업데이트되는지 확인해야 합니다. Northwind 데이터 서비스에서 Customer 항목은 여러 Order 데이터 인스턴스와 연결할 수 있으며 각 Order는 여러 Order_Detail 항목과 연결할 수 있습니다. 데이터 서비스에서 액세스할 수 있는 관계형 모델에 제한이 있기 때문에 Customer 또는 Order를 삭제하기 위해서는 Customer, Order 및 Order_Detail 항목이 연관된 모든 연결을 삭제해야 할 수 있습니다. 연결에 대한 자세한 내용은 엔터티 및 관계 또는 엔터티 데이터 모델 관계를 참조하십시오.
Silverlight 사용자 인터페이스
이 Silverlight용 응용 프로그램의 사용자 인터페이스는 다음 XML 예제에서 보는 것처럼 Page.xaml 스키마에서 초기화됩니다. 이 페이지에는 세 행으로 구성된 표가 있습니다. 0행은 데이터 수정 및 삭제를 실행하는 단추가 있는 가로 스택 패널이고, 1행에는 데이터 표가 있습니다. 2행은 데이터가 로드되거나 오류가 발생할 때 메시지가 표시되는 텍스트 블록입니다.
<UserControl x:Class="SilverlightClientApp3.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" Width="800" Height="800"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="3*"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition MaxWidth="650"/> </Grid.ColumnDefinitions> <StackPanel Orientation="Horizontal" Grid.Column="0" Grid.Row="0"> <Button Content="Delete" Width="75" Height="20" Margin="10" Click="OnDelete"/> <Button Content="Commit" Width="75" Height="20" Margin="10" Click="OnUpdate"/> </StackPanel> <data:DataGrid Name="dataGrid1" Grid.Row="1" Grid.Column="0" AutoGenerateColumns="True" ItemsSource="{Binding}" > </data:DataGrid> <TextBlock x:Name="textBlock" Grid.Row="2" Grid.Column="0" FontFamily="Calibri"/> </Grid> </UserControl>
데이터 업데이트
ADO.NET 데이터 서비스에서 배포하는 데이터를 업데이트하려면 Silverlight용 응용 프로그램에서 다음 비동기 절차를 구현해야 합니다.
-
UpdateObject 메서드를 호출하여 클라이언트 응용 프로그램에서 DataServiceContext의 데이터를 수정합니다. 이 경우 서버의 데이터는 수정되지 않지만 BeginSaveChanges 메서드가 호출될 때 업데이트를 위해 데이터가 변경된 것으로 표시됩니다.
-
첫 번째 매개 변수에서 지정한 콜백 함수로 BeginSaveChanges 메서드를 호출합니다.
-
콜백 함수에서 EndSaveChanges 메서드를 호출하여 BeginSaveChanges 메서드의 결과를 처리합니다.
다음 코드 세그먼트는 업데이트 시나리오의 각 단계를 보여 줍니다.
다음 예제의 OnUpdate 메서드는 사용자가 데이터 표의 데이터를 수정하고 커밋 단추를 클릭하여 선택한 행의 변경 사항을 커밋할 때 실행됩니다. 이 예제에서는 한 번에 한 행만 업데이트합니다. Category 항목은 DataGridEndingEditEventArgs 개체의 SelectedItem을 Category 형식에 캐스팅하여 업데이트하도록 지정됩니다. 이 Category 항목을 변경하면 UpdateObject 메서드를 호출하여 클라이언트 응용 프로그램의 DataServiceContext에서 업데이트됩니다. BeginSaveChanges 메서드는 데이터 서비스 업데이트를 위한 비동기화 프로세스를 시작합니다.
void OnUpdate(object sender, EventArgs args) { if (dataGrid1.SelectedItem == null || dataGrid1.SelectedItems.Count > 1) { textBlock.Text = "Select a single row for update."; return; } Category selectedCategory = (Category)dataGrid1.SelectedItem; try { svcContext.UpdateObject(selectedCategory); textBlock.Text = "Saving Changes..."; svcContext.BeginSaveChanges(OnSaveChangesCompleted, selectedCategory); } catch (DataServiceRequestException ex) { textBlock.Text = "OnUpdate Error: " + ex.Response.ToString(); } }
데이터 서비스에서 OnUpdate 메서드의 결과가 반환되면 콜백 메서드 OnSaveChangesCompleted가 EndSaveChanges를 호출하여 업데이트를 완료합니다.
void OnSaveChangesCompleted(IAsyncResult result) { try { svcContext.EndSaveChanges(result); textBlock.Text = "Completed"; } catch (DataServiceRequestException ex) { textBlock.Text = "OnSaveChangesCompleted Error: " + ex.Response.ToString(); } }
데이터 삭제
Northwind 데이터 서비스에서 배포하는 Category 데이터를 삭제하려면 Silverlight용 응용 프로그램에서 다음 비동기 절차를 구현해야 합니다.
-
콜백 함수로 BeginLoadProperty 메서드를 호출하여 비동기 메서드의 결과를 처리함으로써 삭제할 항목과 연관된 항목을 모두 가져옵니다. 데이터 서비스는 외부 키 제약 조건이 있는 데이터베이스를 기반으로 하기 때문에 관련된 항목을 모두 삭제해야 합니다.
-
EndLoadProperty 메서드가 단계 1의 결과를 가져오는 콜백 메서드를 구현합니다.
-
각 항목에서 DeleteLink 메서드를 호출하여 관련 항목의 바인딩을 해제합니다.
-
DeleteObject 메서드를 호출하여 항목을 삭제합니다.
-
첫 번째 매개 변수에서 지정한 콜백 함수로 BeginSaveChanges 메서드를 호출합니다.
-
콜백 함수에서 EndSaveChanges 메서드를 호출하여 BeginSaveChanges 메서드의 결과를 처리합니다.
사용자가 삭제 단추를 클릭하면 OnDelete 메서드가 트리거되어 Northwind 서비스에서 Category 항목을 삭제하는 일련의 비동기 메서드가 시작됩니다. OnDelete 메서드는 삭제할 Category를 가져온 다음 비동기 메서드 BeginUnBindDeleteCategory로 전달합니다.
void OnDelete(object sender, EventArgs args) { if (dataGrid1.SelectedItem != null) { try { Category Category = (Category)dataGrid1.SelectedItem; BeginUnBindDeleteCategory(Category); textBlock.Text = "Saving Changes..."; } catch (DataServiceRequestException ex) { textBlock.Text = "OnDelete Error: " + ex.Response.ToString(); } } }
BeginUnBindDeleteCategory 메서드는 이전 단계에서 지정한 Category 항목과 연관된 Product 항목을 로드하기 시작합니다. BeginLoadProperty 메서드의 두 번째 매개 변수는 결과를 처리할 콜백 함수, 이 경우에는 EndUnBindDeleteCategory를 지정합니다.
void BeginUnBindDeleteCategory(Category categoryObject) { try {//기본적으로 관계 속성(예: Product.Supplier)이 있을 때 속성을 명시적으로 로드하지 않으면 해당 속성은 Null이 됩니다. //필요 시 로딩을 지원하기 위해 DataServiceContext 클래스에는 동일한 비동기 모델을 따르는 BeginLoadProperty 메서드가 있습니다. //이 메서드에서 원본 엔터티, 속성 이름 및 콜백을 지정할 수 있습니다. (테이블의 고유키라고 보면됩니다.) svcContext.BeginLoadProperty(categoryObject, "Products", EndUnBindDeleteCategory, categoryObject); } catch (DataServiceRequestException ex) { textBlock.Text = "BeginUnBindDeleteCategory Error: " + ex.Response.ToString(); } }
EndUnBindDeleteCategory 메서드는 BeginLoadProperty 메서드의 결과를 처리할 EndLoadProperty 메서드를 호출합니다. 결과는 각 항목에서 DeleteLink 메서드를 호출하는 foreach 루프에 열거되는 연관된 Product 항목입니다.
연관된 Product 항목에 대한 모든 링크가 Category 항목에서 삭제되면 DeleteObject 메서드를 호출하여 Category 항목이 마지막으로 삭제됩니다. 업데이트 예제에 사용된 콜백 함수인 OnSaveChangesCompleted에서 첫 번째 매개 변수로 BeginSaveChanges 메서드를 호출하여 변경 사항을 데이터 서비스로 전달합니다.
void EndUnBindDeleteCategory(IAsyncResult asyncResult) { Category categoryObject = asyncResult.AsyncState as Category; try { svcContext.EndLoadProperty(asyncResult); //Unbind all the Products that are bound to this instance //of Category using the DeleteLink API foreach (Product product in categoryObject.Products) { svcContext.DeleteLink(categoryObject, "Products", product); } svcContext.DeleteObject(categoryObject); svcContext.BeginSaveChanges(OnSaveChangesCompleted, null); // Update the grid. obsvCollCategories.Remove(categoryObject); } catch (DataServiceRequestException ex) { textBlock.Text = "EndUnbindDelete Error: " + ex.Response.ToString(); } }
OnSaveChangesCompleted 메서드는 EndSaveChanges 메서드를 호출하여 Category 및 Product 항목에 대한 링크의 삭제를 완료합니다.
void OnSaveChangesCompleted(IAsyncResult result) { try { svcContext.EndSaveChanges(result); textBlock.Text = "Completed"; } catch (DataServiceRequestException ex) { textBlock.Text = "OnSaveChangesCompleted Error: " + ex.Response.ToString(); } }
다음 코드에서는 이 항목의 샘플에서 사용하는 Page.xaml.cs 파일의 전체 콘텐츠를 보여 줍니다.
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using SilverlightClientApp3.NorthwindSvc; using System.Data.Services.Client; using System.Collections.ObjectModel; namespace SilverlightClientApp3 { public partial class Page : UserControl { NorthwindEntities svcContext; ObservableCollection<Category> obsvCollCategories; public Page() { InitializeComponent(); this.Loaded += OnLoaded; } void OnLoaded(object sender, EventArgs args) { dataGrid1.AutoGeneratingColumn += OnColumnCreated; svcContext = new NorthwindEntities( new Uri("Northwind.svc", UriKind.Relative)); obsvCollCategories = new ObservableCollection<Category>(); OnGetData(null, null); } void OnColumnCreated(object sender, DataGridAutoGeneratingColumnEventArgs e) { if (e.PropertyName == "Products" || e.PropertyName == "Picture") { e.Cancel = true; } } void OnGetData(object sender, EventArgs args) { DataServiceQuery<Category> query = svcContext.Categories; try { textBlock.Text = "Loading Data..."; query.BeginExecute(GetDataCallback, query); } catch (DataServiceRequestException ex) { textBlock.Text = "OnGetData Error: " + ex.Response.ToString(); } } void GetDataCallback(IAsyncResult result) { try { DataServiceQuery<Category> queryResult = (DataServiceQuery<Category>)result.AsyncState; IEnumerable<Category> results = queryResult.EndExecute(result); foreach (Category item in results) obsvCollCategories.Add(item); Dispatcher.BeginInvoke(() => { dataGrid1.DataContext = obsvCollCategories; }); textBlock.Text = "Data Loaded."; } catch (DataServiceRequestException ex) { textBlock.Text = "GetDataCallback Error: " + ex.Response.ToString(); } } void BeginUnBindDeleteCategory(Category categoryObject) { try { svcContext.BeginLoadProperty(categoryObject, "Products", EndUnBindDeleteCategory, categoryObject); } catch (DataServiceRequestException ex) { textBlock.Text = "BeginUnbindDelete Error: " + ex.Response.ToString(); } } void EndUnBindDeleteCategory(IAsyncResult asyncResult) { Category categoryObject = asyncResult.AsyncState as Category; try { svcContext.EndLoadProperty(asyncResult); //Unbind all the Products that are bound to this instance //of Category using the DeleteLink API foreach (Product product in categoryObject.Products) { svcContext.DeleteLink(categoryObject, "Products", product); } svcContext.DeleteObject(categoryObject); svcContext.BeginSaveChanges(OnSaveChangesCompleted, null); obsvCollCategories.Remove(categoryObject); } catch (DataServiceRequestException ex) { textBlock.Text = "EndUnbindDeleteCategory Error: " + ex.Response.ToString(); } } void OnUpdate(object sender, EventArgs args) { if (dataGrid1.SelectedItem == null || dataGrid1.SelectedItems.Count > 1) { textBlock.Text = "Select a single row for update."; return; } Category selectedCategory = (Category)dataGrid1.SelectedItem; try { svcContext.UpdateObject(selectedCategory); textBlock.Text = "Saving Changes..."; svcContext.BeginSaveChanges(OnSaveChangesCompleted, selectedCategory); } catch (DataServiceRequestException ex) { textBlock.Text = "OnUpdate Error: " + ex.Response.ToString(); } } void OnDelete(object sender, EventArgs args) { if (dataGrid1.SelectedItem != null) { try { Category Category = (Category)dataGrid1.SelectedItem; BeginUnBindDeleteCategory(Category); textBlock.Text = "Saving Changes..."; } catch (DataServiceRequestException ex) { textBlock.Text = "OnDelete Error: " + ex.Response.ToString(); } } } void OnSaveChangesCompleted(IAsyncResult result) { try { svcContext.EndSaveChanges(result); textBlock.Text = "Completed"; } catch (DataServiceRequestException ex) { textBlock.Text = "OnSaveChangesCompleted Error: " + ex.Response.ToString(); } } } }
'WPF' 카테고리의 다른 글
초간단 컬렉션에 바인딩하고 마스터/세부 뷰 만들기 (0) | 2009.05.28 |
---|---|
Silverlight SDK Samples (0) | 2009.05.28 |
INotifyPropertyChanged (0) | 2009.05.28 |
Silverlight 2를 사용하여 데이터 중심 웹 응용 프로그램 만들기 (0) | 2009.05.28 |
ObservableCollection<(Of <(T>)>) Class (0) | 2009.05.28 |
Presentation Model. (0) | 2009.05.27 |
[CAL] 간단한 모듈 구성 (0) | 2009.05.12 |
[CAL] Presentation Model (0) | 2009.05.06 |
CAL Development Activities (0) | 2009.04.29 |
[CAL] Composite Application Library 으로 구현하기 (0) | 2009.04.24 |