Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
WCF Data Services ist eine Komponente von .NET Framework zum Erstellen von Diensten, die Daten mithilfe des Open Data Protocol (OData) und unter Verwendung von REST (Representational State Transfer)-Semantik via Internet oder Intranet verfügbar und nutzbar machen. OData macht Daten als durch URIs adressierbare Ressourcen verfügbar. Mit einem OData-basierten Datendienst kann jede Anwendung interagieren, die HTTP-Anforderungen senden und von einem Datendienst zurückgegebene OData-Feeds verarbeiten kann. WCF Data Services enthält außerdem Clientbibliotheken, die umfangreichere Programmierfunktionen bieten, wenn Sie OData-Feeds aus .NET Framework-Anwendungen verarbeiten. Dieses Thema bietet einen Überblick über die Verarbeitung von OData-Feeds in einem Workflow mit bzw. ohne Clientbibliotheken.
Verwenden des OData-Beispieldiensts Northwind
In den Beispielen in diesem Thema wird der Beispieldatendienst Northwind verwendet, der unter https://services.odata.org/Northwind/Northwind.svc/ verfügbar ist. Dieser Dienst wird als Teil des OData-SDK bereitgestellt und bietet schreibgeschützten Zugriff auf die Beispieldatenbank Northwind. Wenn Schreibzugriff oder ein lokaler WCF-Datendienst gewünscht ist, können Sie die Schritte in Schnellstart (WCF Data Services) ausführen und einen lokalen OData-Dienst erstellen, der den Zugriff auf die Northwind-Datenbank ermöglicht. Ersetzen Sie bei Verwendung des Schnellstarts den lokalen URI durch den URI aus dem Beispielcode in diesem Thema.
Verarbeiten eines OData-Feeds mit Clientbibliotheken
WCF Data Services enthält Clientbibliotheken, die Ihnen das Verwenden eines OData-Feeds aus .NET Framework- und Clientanwendungen erleichtern. Diese Bibliotheken vereinfachen das Senden und Empfangen von HTTP-Nachrichten. Sie übersetzen außerdem die Nachrichtennutzlast in CLR-Objekte, die Entitätsdaten darstellen. Die Clientbibliotheken enthalten die beiden Kernklassen DataServiceContext und DataServiceQuery<TElement>. Diese Klassen ermöglichen es Ihnen, einen Datendienst abzufragen und dann die zurückgegebenen Entitätsdaten als CLR-Objekte zu verarbeiten. In diesem Abschnitt werden zwei Ansätze zum Erstellen von Aktivitäten mit Clientbibliotheken vorgestellt.
Hinzufügen eines Dienstverweises zum WCF-Datendienst
Sie können dem OData-Dienst Northwind über das Dialogfeld Dienstverweis hinzufügen in Visual Studio 2012 einen Verweis hinzufügen, um Northwind-Clientbibliotheken zu erstellen.
Beachten Sie Folgendes: Vom Dienst werden keine Dienstvorgänge verfügbar gemacht, und die Liste Dienste enthält Elemente, die die Entitäten darstellen, die vom Northwind-Datendienst verfügbar gemacht werden. Beim Hinzufügen des Dienstverweises werden Klassen für diese Entitäten generiert, die im Clientcode verwendet werden können. In den Beispielen in diesem Thema werden diese Klassen und die NorthwindEntities -Klasse für die Abfragen verwendet.
Hinweis
Weitere Informationen finden Sie unter Generieren der Datendienst-Clientbibliothek (WCF Data Services).
Verwenden von asynchronen Methoden
Es wird empfohlen, asynchron auf WCF Data Services zuzugreifen, um mögliche Latenzprobleme beim Zugriff auf Ressourcen über das Internet zu umgehen. Die WCF Data Services-Clientbibliotheken enthalten asynchrone Methoden zum Aufrufen von Abfragen, und Windows Workflow Foundation (WF) stellt die AsyncCodeActivity-Klasse zum Erstellen von asynchronen Aktivitäten bereit. Abgeleitete AsyncCodeActivity-Aktivitäten können geschrieben werden, um .NET Framework-Klassen zu nutzen, die asynchrone Methoden enthalten. Alternativ kann der Code, der asynchron ausgeführt werden soll, in eine Methode eingefügt und mithilfe eines Delegaten aufgerufen werden. Dieser Abschnitt enthält zwei Beispiele einer von AsyncCodeActivity abgeleiteten Aktivität, von denen eine die asynchronen Methoden der Clientbibliotheken von WCF Data Services und die andere einen Delegaten verwendet.
Hinweis
Weitere Informationen finden Sie unter Asynchrone Vorgänge (WCF Data Services) und Erstellen asynchroner Aktivitäten.
Verwenden von asynchronen Methoden für Clientbibliotheken
Die DataServiceQuery<TElement> -Klasse stellt die BeginExecute - und die EndExecute -Methode zum asynchronen Abfragen eines OData-Diensts bereit. Diese Methoden können von der BeginExecute - und der EndExecute -Überschreibung einer von AsyncCodeActivity abgeleiteten Klasse aufgerufen werden. Wenn die Überschreibung für AsyncCodeActivityBeginExecute zurückgegeben wird, kann der Workflow in den Leerlauf übergehen (nicht jedoch aufrechterhalten werden), und wenn die asynchrone Arbeit abgeschlossen ist, wird EndExecute von der Runtime aufgerufen.
Im folgenden Beispiel wird eine OrdersByCustomer -Aktivität definiert, die über zwei Eingabeargumente verfügt. Das CustomerId -Argument stellt den Kunden dar, der angibt, welche Aufträge zurückgegeben werden sollen, und das ServiceUri -Argument stellt den URI des OData-Diensts dar, der abgefragt werden soll. Da diese Aktivität von AsyncCodeActivity<IEnumerable<Order>> abgeleitet ist, ist auch ein Result -Ausgabeargument vorhanden, mit dem die Ergebnisse der Abfrage zurückgegeben werden. Mit der BeginExecute -Überschreibung wird eine LINQ-Abfrage erstellt, die alle Aufträge des angegebenen Kunden auswählt. Diese Abfrage wird als UserState des übergebenen AsyncCodeActivityContextangegeben. Anschließend wird die BeginExecute -Methode der Abfrage aufgerufen. Beachten Sie, dass Rückruf und Zustand, die an BeginExecute der Abfrage übergeben werden, dem Rückruf bzw. Zustand entsprechen, die an die BeginExecute -Methode der Aktivität übergeben werden. Nachdem die Ausführung der Abfrage abgeschlossen ist, wird die EndExecute -Methode der Aktivität aufgerufen. Die Abfrage wird vom UserStateabgerufen, und anschließend wird die EndExecute -Methode der Abfrage aufgerufen. Von dieser Methode wird ein IEnumerable<T> des angegebenen Entitätstyps zurückgegeben, hier: Order. Da IEnumerable<Order> der generische Typ von AsyncCodeActivity<TResult> ist, wird IEnumerable als ResultOutArgument<T> der Aktivität festgelegt.
class OrdersByCustomer : AsyncCodeActivity<IEnumerable<Order>>
{
[RequiredArgument]
public InArgument<string> CustomerId { get; set; }
[RequiredArgument]
public InArgument<string> ServiceUri { get; set; }
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
NorthwindEntities dataContext = new NorthwindEntities(new Uri(ServiceUri.Get(context)));
// Define a LINQ query that returns Orders and
// Order_Details for a specific customer.
DataServiceQuery<Order> ordersQuery = (DataServiceQuery<Order>)
from o in dataContext.Orders.Expand("Order_Details")
where o.Customer.CustomerID == CustomerId.Get(context)
select o;
// Specify the query as the UserState for the AsyncCodeActivityContext
context.UserState = ordersQuery;
// The callback and state used here are the ones passed into
// the BeginExecute of this activity.
return ordersQuery.BeginExecute(callback, state);
}
protected override IEnumerable<Order> EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
// Get the DataServiceQuery from the context.UserState
DataServiceQuery<Order> ordersQuery = context.UserState as DataServiceQuery<Order>;
// Return an IEnumerable of the query results.
return ordersQuery.EndExecute(result);
}
}
Im folgenden Beispiel wird von der OrdersByCustomer -Aktivität eine Liste mit Aufträgen für den angegebenen Kunden abgerufen, und von einer ForEach<T> -Aktivität werden die zurückgegebenen Bestellungen aufgelistet und die jeweiligen Daten in die Konsole geschrieben.
Variable<IEnumerable<Order>> orders = new Variable<IEnumerable<Order>>();
DelegateInArgument<Order> order = new DelegateInArgument<Order>();
Activity wf = new Sequence
{
Variables = { orders },
Activities =
{
new WriteLine
{
Text = "Calling WCF Data Service..."
},
new OrdersByCustomer
{
ServiceUri = "http://services.odata.org/Northwind/Northwind.svc/",
CustomerId = "ALFKI",
Result = orders
},
new ForEach<Order>
{
Values = orders,
Body = new ActivityAction<Order>
{
Argument = order,
Handler = new WriteLine
{
Text = new InArgument<string>((env) => string.Format("{0:d}", order.Get(env).OrderDate))
}
}
}
}
};
WorkflowInvoker.Invoke(wf);
Beim Aufrufen des Workflows werden die folgenden Daten in die Konsole geschrieben:
Calling WCF Data Service...
8/25/1997
10/3/1997
10/13/1997
1/15/1998
3/16/1998
4/9/1998
Hinweis
Wenn keine Verbindung zum OData-Server hergestellt werden kann, wird eine Ausnahme ähnlich der folgenden angezeigt:
Unbehandelte Ausnahme: System.InvalidOperationException: Fehler beim Verarbeiten dieser Anforderung. ---> System.Net.WebException: Die Verbindung mit dem Remoteserver kann nicht hergestellt werden. ---> System.Net.Sockets.SocketException: Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat.
Eine weitere Verarbeitung der von der Abfrage zurückgegebenen Daten kann ggf. in der EndExecute -Überschreibung der Aktivität erfolgen. BeginExecute und EndExecute werden mit dem Workflowthread aufgerufen, und Code in den Überschreibungen wird nicht asynchron ausgeführt. Wenn die zusätzliche Verarbeitung umfangreich oder langwierig ist, oder wenn die Abfrageergebnisse seitenweise angezeigt werden, kann es empfehlenswert sein, den Ansatz im nächsten Abschnitt zu berücksichtigen. Dabei wird ein Delegat zur Ausführung der Abfrage sowie für weitere asynchrone Verarbeitungen verwendet.
Verwenden von Delegaten
Neben dem Aufrufen der asynchronen Methode einer .NET Framework-Klasse kann die asynchrone Logik auch in einer der Methoden einer AsyncCodeActivity-basierten Aktivität definiert werden. Diese Methode wird mit einem Delegaten in der BeginExecute -Überschreibung der Aktivität angegeben. Nach dem Abschluss der Methode wird die EndExecute -Überschreibung der Methode von der Laufzeit aufgerufen. Beim Aufrufen eines OData-Diensts aus einem Workflow kann diese Methode zum Abfragen des Diensts verwendet werden und weitere Verarbeitungsmöglichkeiten bieten.
Im folgenden Beispiel wird eine ListCustomers -Aktivität definiert. Mit dieser Aktivität wird der Beispieldatendienst Northwind abgefragt und eine List<Customer> mit allen Kunden in der Northwind-Datenbank zurückgegeben. Der asynchrone Vorgang wird von der GetCustomers -Methode ausgeführt. Mit dieser Methode wird der Dienst für alle Kunden abgefragt, und das Ergebnis wird in eine List<Customer>kopiert. Im Anschluss wird überprüft, ob die Ergebnisse seitenweise angegeben sind. Wenn dies der Fall ist, wird die nachfolgende Ergebnisseite vom Dienst abgefragt, die Ergebnisse werden der Liste hinzugefügt, und der Vorgang wird fortgesetzt, bis alle Daten abgerufen wurden.
Hinweis
Weitere Informationen zum Paging in WCF Data Services finden Sie unter Vorgehensweise: Laden von ausgelagerten Ergebnissen (WCF Data Services).
Sobald alle Kunden hinzugefügt wurden, wird die Liste zurückgegeben. Die GetCustomers -Methode wird in der BeginExecute -Überschreibung der Aktivität angegeben. Da die Methode über einen Rückgabewert verfügt, wird eine Func<string, List<Customer>> erstellt, um die Methode anzugeben.
Hinweis
Wenn die Methode, mit der der asynchrone Vorgang ausgeführt wird, nicht über einen Rückgabewert verfügt, wird eine Action anstelle einer Func<TResult> verwendet. Beispiele für das Erstellen eines asynchronen Beispiels mit beiden Ansätzen finden Sie unter Erstellen asynchroner Aktivitäten.
Diese Func<TResult> wird dem UserState zugewiesen, und anschließend wird BeginInvoke aufgerufen. Da die aufzurufende Methode nicht auf die Argumentumgebung der Aktivität zugreifen kann, wird der Wert des ServiceUri -Arguments als erster Parameter zusammen mit dem Rückruf und dem Zustand übergeben, die in BeginExecuteübergeben wurden. Beim Abschluss von GetCustomers wird EndExecutevon der Laufzeit aufgerufen. Mit dem Code in EndExecute wird der Delegat vom UserStateabgerufen, EndInvokewird aufgerufen, und das Ergebnis (die Liste der Kunden, die von der GetCustomers -Methode zurückgegeben wurde) wird zurückgegeben.
class ListCustomers : AsyncCodeActivity<List<Customer>>
{
[RequiredArgument]
public InArgument<string> ServiceUri { get; set; }
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
// Create a delegate that references the method that implements
// the asynchronous work. Assign the delegate to the UserState,
// invoke the delegate, and return the resulting IAsyncResult.
Func<string, List<Customer>> GetCustomersDelegate = new Func<string, List<Customer>>(GetCustomers);
context.UserState = GetCustomersDelegate;
return GetCustomersDelegate.BeginInvoke(ServiceUri.Get(context), callback, state);
}
protected override List<Customer> EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
// Get the delegate from the UserState and call EndInvoke
Func<string, List<Customer>> GetCustomersDelegate = (Func<string, List<Customer>>)context.UserState;
return (List<Customer>)GetCustomersDelegate.EndInvoke(result);
}
List<Customer> GetCustomers(string serviceUri)
{
// Get all customers here and add them to a list. This method doesn't have access to the
// activity's environment of arguments, so the Service Uri is passed in.
// Create the DataServiceContext using the service URI.
NorthwindEntities context = new NorthwindEntities(new Uri(serviceUri));
// Return all customers.
QueryOperationResponse<Customer> response =
context.Customers.Execute() as QueryOperationResponse<Customer>;
// Add them to the list.
List<Customer> customers = new List<Customer>(response);
// Is this the complete list or are the results paged?
DataServiceQueryContinuation<Customer> token;
while ((token = response.GetContinuation()) != null)
{
// Load the next page of results.
response = context.Execute<Customer>(token) as QueryOperationResponse<Customer>;
// Add the next page of customers to the list.
customers.AddRange(response);
}
// Return the list of customers
return customers;
}
}
Im folgenden Beispiel wird von der ListCustomers -Aktivität eine Liste mit Kunden abgerufen. Die ForEach<T> -Aktivität durchläuft die Kunden und schreibt den Namen des Unternehmens und den Ansprechpartner für jeden Kunden in die Konsole.
Variable<List<Customer>> customers = new Variable<List<Customer>>();
DelegateInArgument<Customer> customer = new DelegateInArgument<Customer>();
Activity wf = new Sequence
{
Variables = { customers },
Activities =
{
new WriteLine
{
Text = "Calling WCF Data Service..."
},
new ListCustomers
{
ServiceUri = "http://services.odata.org/Northwind/Northwind.svc/",
Result = customers
},
new ForEach<Customer>
{
Values = customers,
Body = new ActivityAction<Customer>
{
Argument = customer,
Handler = new WriteLine
{
Text = new InArgument<string>((env) => string.Format("{0}, Contact: {1}",
customer.Get(env).CompanyName, customer.Get(env).ContactName))
}
}
}
}
};
WorkflowInvoker.Invoke(wf);
Beim Aufrufen des Workflows werden die folgenden Daten in die Konsole geschrieben. Da von dieser Abfrage zahlreiche Kunden zurückgegeben werden, wird an dieser Stelle nur ein Teil der Ausgabe angezeigt.
Calling WCF Data Service...
Alfreds Futterkiste, Contact: Maria Anders
Ana Trujillo Emparedados y helados, Contact: Ana Trujillo
Antonio Moreno Taquería, Contact: Antonio Moreno
Around the Horn, Contact: Thomas Hardy
Berglunds snabbköp, Contact: Christina Berglund
...
Verarbeiten eines OData-Feeds ohne Clientbibliotheken
OData macht Daten als durch URIs adressierbare Ressourcen verfügbar. Diese URIs werden bei der Verwendung von Clientbibliotheken für Sie erstellt, eine Verwendung von Clientbibliotheken ist jedoch nicht erforderlich. Der Zugriff auf OData-Dienste ist auch direkt und ohne Clientbibliotheken möglich. Wenn Sie keine Clientbibliotheken verwenden, werden der Speicherort des Diensts sowie die gewünschten Daten durch den URI angegeben, und die Ergebnisse werden in der Antwort auf die HTTP-Anforderung zurückgegeben. Die Rohdaten können anschließend nach Bedarf verarbeitet oder geändert werden. Eine Möglichkeit, die Ergebnisse einer OData-Abfrage abzurufen, besteht in der Verwendung der WebClient -Klasse. In diesem Beispiel wird der Name des Ansprechpartners für den Kunden abgerufen, der durch Schlüssel ALFKI dargestellt wird.
string uri = "http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/ContactName";
WebClient client = new WebClient();
string data = client.DownloadString(uri);
Console.WriteLine($"Raw data returned:\n{data}");
Wenn dieser Code ausgeführt wird, wird die folgende Ausgabe in der Konsole angezeigt:
Raw data returned:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ContactName xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">Maria Anders</ContactName>
Der Code aus diesem Beispiel kann in einem Workflow in die Execute-Überschreibung einer CodeActivity-basierten benutzerdefinierten Aktivität eingebunden werden. Dieselbe Funktionalität kann jedoch auch mit der InvokeMethod<TResult>-Aktivität bereitgestellt werden. Mit der InvokeMethod<TResult> -Aktivität können Workflowautoren statische Methoden und Instanzmethoden von Klassen aufrufen. Außerdem verfügen sie damit über eine Möglichkeit, die angegebene Methode asynchron aufzurufen. Im folgenden Beispiel wird eine InvokeMethod<TResult> -Aktivität konfiguriert, um die DownloadString -Methode der WebClient -Klasse aufzurufen und eine Liste mit Kunden zurückzugeben.
new InvokeMethod<string>
{
TargetObject = new InArgument<WebClient>(new VisualBasicValue<WebClient>("New System.Net.WebClient()")),
MethodName = "DownloadString",
Parameters =
{
new InArgument<string>("http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/Orders")
},
Result = data,
RunAsynchronously = true
},
MitInvokeMethod<TResult> können Sie statische Methoden und Instanzenmethoden von Klassen aufrufen. Da DownloadString eine Instanzmethode der WebClient -Klasse ist, wird eine neue Instanz der WebClient -Klasse für TargetObjectangegeben.
DownloadString wird als MethodNameangegeben, der URI, der die Abfrage enthält, wird in der Parameters -Auflistung angegeben, und der Rückgabewert wird dem Result -Wert zugewiesen. Der RunAsynchronously -Wert wird auf truefestgelegt, d. h., die Methode wird hinsichtlich des Workflows asynchron aufgerufen. Im folgenden Beispiel wird ein Workflow erstellt, in dem der Beispieldatendienst Northwind mit der InvokeMethod<TResult> -Aktivität abgefragt wird, um eine Liste der Aufträge für einen bestimmten Kunden zurückzugeben und die zurückgegebenen Daten in die Konsole zu schreiben.
Variable<string> data = new Variable<string>();
Activity wf = new Sequence
{
Variables = { data },
Activities =
{
new WriteLine
{
Text = "Calling WCF Data Service..."
},
new InvokeMethod<string>
{
TargetObject = new InArgument<WebClient>(new VisualBasicValue<WebClient>("New System.Net.WebClient()")),
MethodName = "DownloadString",
Parameters =
{
new InArgument<string>("http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/Orders")
},
Result = data,
RunAsynchronously = true
},
new WriteLine
{
Text = new InArgument<string>(env => string.Format("Raw data returned:\n{0}", data.Get(env)))
}
}
};
WorkflowInvoker.Invoke(wf);
Wenn dieser Workflow aufgerufen wird, wird die folgende Ausgabe in der Konsole angezeigt. Da von dieser Abfrage zahlreiche Aufträge zurückgegeben werden, wird an dieser Stelle nur ein Teil der Ausgabe angezeigt.
Calling WCF Data Service...
Raw data returned:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>*
<feed
xml:base="http://services.odata.org/Northwind/Northwind.svc/"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns="http://www.w3.org/2005/Atom">
<title type="text">Orders\</title>
<id>http://services.odata.org/Northwind/Northwind.svc/Customers('ALFKI')/Orders\</id>
<updated>2010-05-19T19:37:07Z\</updated>
<link rel="self" title="Orders" href="Orders" />
<entry>
<id>http://services.odata.org/Northwind/Northwind.svc/Orders(10643)\</id>
<title type="text">\</title>
<updated>2010-05-19T19:37:07Z\</updated>
<author>
<name />
</author>
<link rel="edit" title="Order" href="Orders(10643)" />
<link rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/Customer" type="application/atom+xml;type=entry" title="Customer" href="Orders(10643)/Customer" />
...
Dieses Beispiel enthält eine Methode, die Workflowanwendungsautoren verwenden können, um die Rohdaten zu nutzen, die von einem OData-Dienst zurückgegeben werden. Weitere Informationen zum Zugreifen auf WCF Data Services mit URIs finden Sie unter Zugreifen auf Datendienstressourcen (WCF Data Services) und OData: URI-Konventionen.