다음을 통해 공유


서비스 작업 및 동작 호출(WCF Data Services)

Open Data Protocol(OData)은 데이터 서비스에 대한 서비스 작업과 서비스 동작을 모두 정의합니다. 다른 데이터 서비스 리소스와 마찬가지로, 서비스 작업 및 서비스 동작은 URI을 사용하여 지정합니다. 서비스 작업과 동작은 모두 엔터티 형식의 컬렉션, 단일 엔터티 형식 인스턴스, 기본 형식(예: 정수 및 문자열), null(Visual Basic의 경우 Nothing)을 반환할 수 있습니다. 서비스 작업과 달리 서비스 동작은 데이터 모델 리소스에 바인딩할 수 있으며 시스템에 의도하지 않은 결과를 가져올 수 있으므로 HTTP POST 요청으로 호출해야 합니다. 자세한 내용은 서비스 작업(WCF Data Services)OData 동작을 사용하여 서버 쪽 동작 구현을 참조하십시오.

서비스 작업과 서비스 동작은 모두 OData를 구현하는 데이터 서비스에서 반환하는 메타데이터에 노출됩니다. 메타데이터에서 두 항목은 모두 FunctionImport 요소로 표현됩니다. 강력한 형식의 DataServiceContext를 생성할 경우 서비스 참조 추가 및 DataSvcUtil.exe 도구는 이 요소를 무시합니다. 이 때문에 서비스 작업을 직접 호출하는 데 사용할 수 있는 컨텍스트에서 메서드를 찾을 수 없습니다. 그러나, 다음 두 가지 중 한 가지 방법으로 WCF Data Services 클라이언트를 사용하여 서비스 작업을 호출할 수 있습니다.

서비스 작업 및 서비스 동작 호출에 대한 고려 사항

WCF Data Services 클라이언트를 사용하여 서비스 작업을 호출하는 경우 다음과 같은 사항을 고려해야 합니다.

서비스 작업 호출 예제

이 단원에는 WCF Data Services 클라이언트 라이브러리를 사용하여 서비스 작업을 호출하는 방법에 대한 다음 예제가 나와 있습니다.

Execute<T>를 호출하여 엔터티 컬렉션 반환

다음 예제는 city 문자열 매개 변수를 사용하고 IQueryable<T>을 반환하는 GetOrdersByCity라는 서비스 작업을 호출합니다.

' Define the service operation query parameter.
Dim city As String = "London"

' Define the query URI to access the service operation with specific 
' query options relative to the service URI.
Dim queryString As String = String.Format("GetOrdersByCity?city='{0}'", city) _
                            & "&$orderby=ShippedDate desc" _
                            & "&$expand=Order_Details"

' Create the DataServiceContext using the service URI.
Dim context As NorthwindEntities = New NorthwindEntities(svcUri2)

Try

    ' Execute the service operation that returns all orders for the specified city.
    Dim results = context.Execute(Of Order)(New Uri(queryString, UriKind.Relative))

    ' Write out order information.
    For Each o As Order In results
        Console.WriteLine(String.Format("Order ID: {0}", o.OrderID))
        For Each item As Order_Detail In o.Order_Details
            Console.WriteLine(String.Format(vbTab & "Item: {0}, quantity: {1}", _
                item.ProductID, item.Quantity))
        Next
    Next
Catch ex As DataServiceQueryException
    Dim response As QueryOperationResponse = ex.Response

    Console.WriteLine(response.Error.Message)
End Try
// Define the service operation query parameter.
string city = "London";

// Define the query URI to access the service operation with specific 
// query options relative to the service URI.
string queryString = string.Format("GetOrdersByCity?city='{0}'", city)
    + "&$orderby=ShippedDate desc"
    + "&$expand=Order_Details";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

try
{
    // Execute the service operation that returns all orders for the specified city.
    var results = context.Execute<Order>(new Uri(queryString, UriKind.Relative));

    // Write out order information.
    foreach (Order o in results)
    {
        Console.WriteLine(string.Format("Order ID: {0}", o.OrderID));

        foreach (Order_Detail item in o.Order_Details)
        {
            Console.WriteLine(String.Format("\tItem: {0}, quantity: {1}",
                item.ProductID, item.Quantity));
        }
    }
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

이 예제에서는 서비스 작업이 관련 Order_Detail 개체를 사용하여 Order 개체의 컬렉션을 반환합니다.

CreateQuery<T>를 사용하여 엔터티 컬렉션 반환

다음 예제에서는 CreateQuery<T>(String)를 사용하여 동일한 GetOrdersByCity 서비스 작업을 호출하는 데 사용되는 DataServiceQuery<TElement>를 반환합니다.

' Define the service operation query parameter.
Dim city As String = "London"

' Create the DataServiceContext using the service URI.
Dim context As NorthwindEntities = New NorthwindEntities(svcUri2)

' Use the CreateQuery method to create a query that accessess
' the service operation passing a single parameter.       
Dim query = context.CreateQuery(Of Order)("GetOrdersByCity") _
        .AddQueryOption("city", String.Format("'{0}'", city)).Expand("Order_Details")

Try
    ' The query is executed during enumeration.
    For Each o As Order In query
        Console.WriteLine(String.Format("Order ID: {0}", o.OrderID))
        For Each item As Order_Detail In o.Order_Details
            Console.WriteLine(String.Format(vbTab & "Item: {0}, quantity: {1}", _
                item.ProductID, item.Quantity))
        Next
    Next
Catch ex As DataServiceQueryException
    Dim response As QueryOperationResponse = ex.Response
    Console.WriteLine(response.Error.Message)
End Try
// Define the service operation query parameter.
string city = "London";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

// Use the CreateQuery method to create a query that accessess
// the service operation passing a single parameter.       
var query = context.CreateQuery<Order>("GetOrdersByCity")
    .AddQueryOption("city", string.Format("'{0}'", city))
    .Expand("Order_Details");

try
{
    // The query is executed during enumeration.
    foreach (Order o in query)
    {
        Console.WriteLine(string.Format("Order ID: {0}", o.OrderID));

        foreach (Order_Detail item in o.Order_Details)
        {
            Console.WriteLine(String.Format("\tItem: {0}, quantity: {1}",
                item.ProductID, item.Quantity));
        }
    }
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

이 예제에서 AddQueryOption(String, Object) 메서드는 쿼리에 매개 변수를 추가하는 데 사용되고 Expand(String) 메서드는 관련 Order_Details 개체를 결과에 포함하는 데 사용됩니다.

Execute<T>를 호출하여 단일 엔터티 반환

다음 예제에서는 단일 Order 엔터티만 반환하는 GetNewestOrder라는 서비스 작업을 호출합니다.

' Define the query URI to access the service operation, 
' relative to the service URI.
Dim queryString As String = "GetNewestOrder"

' Create the DataServiceContext using the service URI.
Dim context As NorthwindEntities = New NorthwindEntities(svcUri2)

Try
    ' Execute a service operation that returns only the newest single order.
    Dim o As Order = _
        context.Execute(Of Order)( _
            New Uri(queryString, UriKind.Relative)).FirstOrDefault()

    ' Write out order information.
    Console.WriteLine(String.Format("Order ID: {0}", o.OrderID))
    Console.WriteLine(String.Format("Order date: {0}", o.OrderDate))
Catch ex As DataServiceQueryException
    Dim response As QueryOperationResponse = ex.Response

    Console.WriteLine(response.Error.Message)
End Try
// Define the query URI to access the service operation, 
// relative to the service URI.
string queryString = "GetNewestOrder";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

try
{
    // Execute a service operation that returns only the newest single order.
    Order order
        = (context.Execute<Order>(new Uri(queryString, UriKind.Relative)))
        .FirstOrDefault();

    // Write out order information.
    Console.WriteLine(string.Format("Order ID: {0}", order.OrderID));
    Console.WriteLine(string.Format("Order date: {0}", order.OrderDate));
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

이 예제에서 FirstOrDefault<TSource>(IEnumerable<TSource>) 메서드는 실행 시 단일 Order 엔터티만 요청하는 데 사용됩니다.

Execute<T>를 호출하여 기본 값 컬렉션 반환

다음 예제에서는 문자열 값의 컬렉션을 반환하는 서비스 작업을 호출합니다.

' Define the query URI to access the service operation, 
' relative to the service URI.
Dim queryString As String = "GetCustomerNames"

'Create the DataServiceContext using the service URI.
Dim context As NorthwindEntities = New NorthwindEntities(svcUri2)

Try

    ' Execute a service operation that returns a collection of customer names.
    Dim customerNames As IEnumerable(Of String) _
        = context.Execute(Of String)(New Uri(queryString, UriKind.Relative))

    For Each name As String In customerNames
        ' Write out customer information.
        Console.WriteLine(name)
    Next

Catch ex As DataServiceQueryException
    Dim response As QueryOperationResponse = ex.Response

    Console.WriteLine(response.Error.Message)
End Try
// Define the query URI to access the service operation, 
// relative to the service URI.
string queryString = "GetCustomerNames";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

try
{
    // Execute a service operation that returns a collection of customer names
    IEnumerable<string> customerNames
        = context.Execute<string>(new Uri(queryString, UriKind.Relative));

    foreach (string name in customerNames)
    {
        // Write out customer information.
        Console.WriteLine(name);
    }
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

Execute<T>를 호출하여 단일 기본 값 반환

다음 예제에서는 단일 문자열 값을 반환하는 서비스 작업을 호출합니다.

' Define the query URI to access the service operation, 
' relative to the service URI.
Dim queryString As String = "CountOpenOrders"

' Create the DataServiceContext using the service URI.
Dim context As NorthwindEntities = New NorthwindEntities(svcUri2)

Try
    ' Execute a service operation that returns the integer 
    ' count of open orders.
    Dim numOrders As Integer = context.Execute(Of Integer)( _
        New Uri(queryString, UriKind.Relative)).FirstOrDefault()

    ' Write out the number of open orders.
    Console.WriteLine(String.Format("Open orders as of {0}: {1}",
        DateTime.Today.Date, numOrders))
Catch ex As DataServiceQueryException
    Dim response As QueryOperationResponse = ex.Response

    Console.WriteLine(response.Error.Message)
End Try
// Define the query URI to access the service operation, 
// relative to the service URI.
string queryString = "CountOpenOrders";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

try
{
    // Execute a service operation that returns the integer 
    // count of open orders.
    int numOrders
        = (context.Execute<int>(new Uri(queryString, UriKind.Relative)))
        .FirstOrDefault();

    // Write out the number of open orders.
    Console.WriteLine(string.Format("Open orders as of {0}: {1}",
        DateTime.Today.Date, numOrders));
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

이 예제에서는 다시 FirstOrDefault<TSource>(IEnumerable<TSource>) 메서드를 사용하여 실행 시 단일 정수 값만 요청합니다.

데이터를 반환하지 않는 서비스 작업 호출

다음 예제에서는 데이터를 반환하지 않는 서비스 작업을 호출합니다.

' Define the query URI to access the service operation, 
' relative to the service URI.
Dim queryString As String = "ReturnsNoData"

' Create the DataServiceContext using the service URI.
Dim context As NorthwindEntities = New NorthwindEntities(svcUri2)

Try
    ' Execute a service operation that returns void.
    context.Execute(Of String)( _
        New Uri(queryString, UriKind.Relative))
Catch ex As DataServiceQueryException
    Dim response As QueryOperationResponse = ex.Response

    Console.WriteLine(response.Error.Message)
End Try
// Define the query URI to access the service operation, 
// relative to the service URI.
string queryString = "ReturnsNoData";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

try
{
    // Execute a service operation that returns void.
    context.Execute<string>(new Uri(queryString, UriKind.Relative));
}
catch (DataServiceQueryException ex)
{
    QueryOperationResponse response = ex.Response;

    Console.WriteLine(response.Error.Message);
}

데이터가 반환되지 않기 때문에 실행 값이 할당되지 않습니다. 요청이 성공했다는 유일한 표시는 DataServiceQueryException이 발생하지 않는다는 것입니다.

서비스 작업을 비동기적으로 호출

다음 예제에서는 BeginExecute<TElement>(Uri, AsyncCallback, Object)EndExecute<TElement>(IAsyncResult)를 호출하여 서비스 작업을 비동기적으로 호출합니다.

' Define the service operation query parameter.
Dim city As String = "London"

' Define the query URI to access the service operation with specific 
' query options relative to the service URI.
Dim queryString As String = String.Format("GetOrdersByCity?city='{0}'", city) _
        & "&$orderby=ShippedDate desc" _
        & "&$expand=Order_Details"

' Create the DataServiceContext using the service URI.
Dim context As NorthwindEntities = New NorthwindEntities(svcUri2)

' Define the delegate to callback into the process
Dim callback As AsyncCallback = AddressOf OnAsyncExecutionComplete

' Execute the service operation that returns 
' all orders for the specified city.
Dim results = context.BeginExecute(Of Order)( _
    New Uri(queryString, UriKind.Relative), _
    callback, context)
// Define the service operation query parameter.
string city = "London";

// Define the query URI to access the service operation with specific 
// query options relative to the service URI.
string queryString = string.Format("GetOrdersByCity?city='{0}'", city)
    + "&$orderby=ShippedDate desc"
    + "&$expand=Order_Details";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

// Execute the service operation that returns 
// all orders for the specified city.
var results = context.BeginExecute<Order>(
    new Uri(queryString, UriKind.Relative),
    OnAsyncExecutionComplete, context);
Private Shared Sub OnAsyncExecutionComplete(ByVal result As IAsyncResult)

    ' Get the context back from the stored state.
    Dim context = TryCast(result.AsyncState, NorthwindEntities)

    Try
        ' Complete the exection and write out the results.
        For Each o As Order In context.EndExecute(Of Order)(result)
            Console.WriteLine(String.Format("Order ID: {0}", o.OrderID))

            For Each item As Order_Detail In o.Order_Details
                Console.WriteLine(String.Format(vbTab & "Item: {0}, quantity: {1}", _
                    item.ProductID, item.Quantity))
            Next
        Next
    Catch ex As DataServiceQueryException
        Dim response As QueryOperationResponse = ex.Response
        Console.WriteLine(response.Error.Message)
    End Try
End Sub
private static void OnAsyncExecutionComplete(IAsyncResult result)
{
    // Get the context back from the stored state.
    var context = result.AsyncState as NorthwindEntities;

    try
    {
        // Complete the exection and write out the results.
        foreach (Order o in context.EndExecute<Order>(result))
        {
            Console.WriteLine(string.Format("Order ID: {0}", o.OrderID));

            foreach (Order_Detail item in o.Order_Details)
            {
                Console.WriteLine(String.Format("\tItem: {0}, quantity: {1}",
                    item.ProductID, item.Quantity));
            }
        }
    }
    catch (DataServiceQueryException ex)
    {
        QueryOperationResponse response = ex.Response;

        Console.WriteLine(response.Error.Message);
    }
}

데이터가 반환되지 않기 때문에 실행으로 반환된 값이 할당되지 않습니다. 요청이 성공했다는 유일한 표시는 DataServiceQueryException이 발생하지 않는다는 것입니다.

다음 예제에서는 CreateQuery<T>(String)를 사용하여 동일한 서비스 작업을 비동기적으로 호출합니다.

' Define the service operation query parameter.
Dim city As String = "London"

' Create the DataServiceContext using the service URI.
Dim context As NorthwindEntities = New NorthwindEntities(svcUri2)

' Use the CreateQuery method to create a query that accessess
' the service operation passing a single parameter.       
Dim query = context.CreateQuery(Of Order)("GetOrdersByCity") _
            .AddQueryOption("city", String.Format("'{0}'", city)) _
            .Expand("Order_Details")

' Define the delegate to callback into the process
Dim callback As AsyncCallback = AddressOf OnAsyncQueryExecutionComplete

' Execute the service operation that returns 
' all orders for the specified city.
Dim results = _
    query.BeginExecute(callback, query)
// Define the service operation query parameter.
string city = "London";

// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(svcUri2);

// Use the CreateQuery method to create a query that accessess
// the service operation passing a single parameter.       
var query = context.CreateQuery<Order>("GetOrdersByCity")
    .AddQueryOption("city", string.Format("'{0}'", city))
    .Expand("Order_Details");

// Execute the service operation that returns 
// all orders for the specified city.
var results = 
    query.BeginExecute(OnAsyncQueryExecutionComplete, query);
Private Shared Sub OnAsyncQueryExecutionComplete(ByVal result As IAsyncResult)
    ' Get the query back from the stored state.
    Dim query = TryCast(result.AsyncState, DataServiceQuery(Of Order))

    Try
        ' Complete the exection and write out the results.
        For Each o As Order In query.EndExecute(result)

            Console.WriteLine(String.Format("Order ID: {0}", o.OrderID))

            For Each item As Order_Detail In o.Order_Details
                Console.WriteLine(String.Format(vbTab & "Item: {0}, quantity: {1}", _
                    item.ProductID, item.Quantity))
            Next
        Next
    Catch ex As DataServiceQueryException
        Dim response As QueryOperationResponse = ex.Response

        Console.WriteLine(response.Error.Message)
    End Try
End Sub
private static void OnAsyncQueryExecutionComplete(IAsyncResult result)
{
    // Get the query back from the stored state.
    var query = result.AsyncState as DataServiceQuery<Order>;

    try
    {
        // Complete the exection and write out the results.
        foreach (Order o in query.EndExecute(result))
        {
            Console.WriteLine(string.Format("Order ID: {0}", o.OrderID));

            foreach (Order_Detail item in o.Order_Details)
            {
                Console.WriteLine(String.Format("\tItem: {0}, quantity: {1}",
                    item.ProductID, item.Quantity));
            }
        }
    }
    catch (DataServiceQueryException ex)
    {
        QueryOperationResponse response = ex.Response;

        Console.WriteLine(response.Error.Message);
    }
}

참고 항목

관련 자료

데이터 클라이언트(WCF Data Services)