Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Data Services WCF adalah komponen dari .NET Framework yang memungkinkan Anda membuat layanan yang menggunakan Open Data Protocol (OData) untuk mengekspos dan menggunakan data melalui Web atau intranet dengan menggunakan semantik transfer status representasional (REST). OData memaparkan data sebagai sumber daya yang dapat diatasi oleh URI. Aplikasi apa pun dapat berinteraksi dengan layanan data berbasis OData jika dapat mengirim permintaan HTTP dan memproses umpan OData yang dikembalikan layanan data. Selain itu, WCF Data Services mencakup pustaka klien yang memberikan pengalaman pemrograman yang lebih kaya saat Anda menggunakan umpan OData dari aplikasi .NET Framework. Topik ini memberikan gambaran umum tentang menggunakan umpan OData dalam alur kerja dengan dan tanpa menggunakan pustaka klien.
Menggunakan layanan sampel Northwind OData
Contoh dalam topik ini menggunakan sampel layanan data Northwind yang terletak di https://services.odata.org/Northwind/Northwind.svc/. Layanan ini disediakan sebagai bagian dari OData SDK dan menyediakan akses baca-saja ke database Northwind sampel. Jika akses tulis diinginkan, atau jika WCF Data Service lokal diinginkan, Anda dapat mengikuti langkah-langkah dari Panduan Cepat WCF Data Services untuk membuat OData service lokal yang menyediakan akses ke database Northwind. Jika Anda mengikuti panduan memulai cepat, ganti URI lokal dengan yang disediakan dalam topik kode contoh ini.
Mengonsumsi umpan OData dengan pustaka klien
Data Services WCF mencakup pustaka klien yang memungkinkan Anda untuk lebih mudah menggunakan umpan OData dari .NET Framework dan aplikasi klien. Pustaka ini menyederhanakan pengiriman dan penerimaan pesan HTTP. Mereka juga menerjemahkan payload pesan ke dalam objek CLR yang mewakili data entitas. Pustaka klien menampilkan dua kelas inti DataServiceContext dan DataServiceQuery<TElement>. Kelas-kelas ini memungkinkan Anda untuk mengkueri layanan data lalu bekerja dengan data entitas yang dikembalikan sebagai objek CLR. Bagian ini mencakup dua pendekatan untuk membuat aktivitas yang menggunakan pustaka klien.
Menambahkan referensi layanan ke layanan Data WCF
Untuk menghasilkan pustaka klien Northwind, Anda bisa menggunakan kotak dialog Tambahkan Referensi Layanan di Visual Studio 2012 untuk menambahkan referensi ke layanan OData Northwind.
Perhatikan bahwa tidak ada operasi layanan yang diekspos oleh layanan, dan dalam daftar Layanan ada item yang mewakili entitas yang diekspos oleh layanan data Northwind. Ketika referensi layanan ditambahkan, kelas akan dihasilkan untuk entitas ini dan dapat digunakan dalam kode klien. Contoh dalam topik ini menggunakan kelas ini dan kelas NorthwindEntities untuk melakukan kueri.
Catatan
Untuk informasi selengkapnya, lihat Membuat Pustaka Klien Layanan Data (WCF Data Services).
Menggunakan metode asinkron
Untuk mengatasi kemungkinan masalah latensi yang mungkin terjadi saat mengakses sumber daya melalui Web, sebaiknya akses WCF Data Services secara asinkron. Pustaka klien WCF Data Services mencakup metode asinkron untuk memanggil kueri, dan Windows Workflow Foundation (WF) menyediakan kelas AsyncCodeActivity untuk penulisan aktivitas asinkron. Aktivitas turunan AsyncCodeActivity dapat ditulis untuk memanfaatkan .NET Framework kelas yang memiliki metode asinkron, atau kode yang akan dijalankan secara asinkron dapat dimasukkan ke dalam metode dan dipanggil dengan menggunakan delegasi. Bagian ini menyediakan dua contoh aktivitas turunan AsyncCodeActivity; satu yang menggunakan metode asinkron pustaka klien WCF Data Services dan satu yang menggunakan delegasi.
Catatan
Untuk informasi selengkapnya, lihat Operasi Asinkron (WCF Data Services) dan Membuat Aktivitas Asinkron.
Menggunakan metode asinkron pustaka klien
Kelas DataServiceQuery<TElement> menyediakan metode BeginExecute dan EndExecute untuk mengkueri layanan OData secara asinkron. Metode ini dapat dipanggil dari penggantian BeginExecute dan EndExecute dalam kelas turunan AsyncCodeActivity. AsyncCodeActivity BeginExecute Ketika penimpaan kembali, alur kerja dapat diam (tetapi tidak bertahan), dan ketika pekerjaan asinkron selesai, EndExecute dipanggil oleh runtime.
Dalam contoh berikut, aktivitas OrdersByCustomer didefinisikan yang memiliki dua argumen input. Argumen CustomerId mewakili pelanggan yang mengidentifikasi pesanan mana yang akan dikembalikan, dan argumen ServiceUri mewakili URI layanan OData yang akan dikueri. Karena aktivitas berasal dari AsyncCodeActivity<IEnumerable<Order>> ada juga output argumen Result yang digunakan untuk mengembalikan hasil kueri. Penggantian BeginExecute membuat kueri LINQ yang memilih semua pesanan dari pelanggan yang ditentukan. Kueri ini ditentukan sebagai UserState dari AsyncCodeActivityContext yang diteruskan, lalu metode BeginExecute dari kueri dipanggil. Perhatikan bahwa panggilan balik dan status yang diteruskan ke kueri BeginExecute adalah yang diteruskan ke metode aktivitas BeginExecute. Ketika kueri telah selesai dieksekusi, metode aktivitas EndExecute dipanggil. Kueri diambil dari UserState, lalu metode kueri EndExecute dipanggil. Metode ini mengembalikan IEnumerable<T> dari jenis entitas yang ditentukan; dalam hal ini Order. Karena IEnumerable<Order> adalah jenis generik dari AsyncCodeActivity<TResult>, IEnumerable ini ditetapkan sebagai ResultOutArgument<T> dari aktivitas.
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);
}
}
Dalam contoh berikut, aktivitas OrdersByCustomer mengambil daftar pesanan untuk pelanggan yang ditentukan, lalu aktivitas ForEach<T> menghitung pesanan yang dikembalikan dan menulis tanggal setiap pesanan ke konsol.
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);
Ketika alur kerja ini dipanggil, data berikut ditulis ke konsol:
Calling WCF Data Service...
8/25/1997
10/3/1997
10/13/1997
1/15/1998
3/16/1998
4/9/1998
Catatan
Jika koneksi ke server OData tidak dapat dibuat, Anda akan mendapatkan pengecualian yang mirip dengan pengecualian berikut:
Pengecualian Tidak Tertangani: System.InvalidOperationException: Terjadi kesalahan saat memproses permintaan ini. ---> System.Net.WebException: Tidak dapat tersambung ke server jarak jauh ---> System.Net.Sockets.SocketException: Upaya koneksi gagal karena pihak yang terhubung tidak merespons dengan benar setelah jangka waktu tertentu, atau koneksi yang dibuat gagal karena host yang terhubung gagal merespons.
Jika ada pemrosesan tambahan yang diperlukan untuk data yang dikembalikan oleh kueri, itu dapat dilakukan dalam override aktivitas EndExecute. Baik BeginExecute dan EndExecute dipanggil dengan menggunakan alur kerja, dan kode apa pun dalam pengambilalihan ini tidak berjalan secara asinkron. Jika pemrosesan tambahan ekstensif atau berjalan lama, atau hasil kueri dipaginasi, Anda harus mempertimbangkan pendekatan yang dibahas di bagian berikutnya, yang menggunakan delegasi untuk menjalankan kueri dan melakukan pemrosesan tambahan secara asinkron.
Menggunakan delegasi
Selain memanggil metode asinkron dari kelas .NET Framework, aktivitas berbasis AsyncCodeActivity juga dapat menentukan logika asinkron dalam salah satu metodenya. Metode ini ditentukan dengan menggunakan delegasi dalam penggantian aktivitas BeginExecute. Saat metode kembali, runtime memanggil penggantian aktivitas EndExecute. Saat memanggil layanan OData dari alur kerja, metode ini dapat digunakan untuk mengkueri layanan dan menyediakan pemrosesan tambahan.
Dalam contoh berikut, aktivitas ListCustomers didefinisikan. Aktivitas ini meminta sampel layanan data Northwind dan mengembalikan List<Customer> yang berisi semua pelanggan dalam database Northwind. Pekerjaan asinkron dilakukan oleh metode GetCustomers. Metode ini meminta layanan untuk semua pelanggan, lalu menyalinnya ke dalam List<Customer>. Kemudian diperiksa untuk memastikan apakah hasilnya terbagi dalam halaman. Jika demikian, sistem menanyakan layanan untuk halaman hasil berikutnya, menambahkannya ke daftar, dan proses ini berlanjut hingga semua data pelanggan berhasil diambil.
Catatan
Untuk informasi selengkapnya tentang halaman di Layanan Data WCF, lihat Cara: Memuat Hasil Halaman (WCF Data Services).
Setelah semua pelanggan ditambahkan, daftar akan dikembalikan. Metode GetCustomers ditentukan dalam penggantian aktivitas BeginExecute. Karena metode memiliki nilai pengembalian, Func<string, List<Customer>> dibuat untuk menentukan metode.
Catatan
Jika metode yang melakukan pekerjaan asinkron tidak memiliki nilai pengembalian, Action digunakan alih-alih Func<TResult>. Untuk contoh pembuatan contoh asinkron menggunakan kedua pendekatan, lihat Membuat Aktivitas Asinkron.
Elemen Func<TResult> ini ditetapkan ke elemen UserState, dan kemudian BeginInvoke dipanggil. Karena metode yang akan dipanggil tidak memiliki akses ke lingkungan argumen aktivitas, nilai argumen ServiceUri diteruskan sebagai parameter pertama, bersama dengan panggilan balik dan status yang diteruskan ke BeginExecute. Saat GetCustomers kembali, runtime memanggil EndExecute. Kode dalam EndExecute mengambil delegasi dari UserState, memanggil EndInvoke, dan mengembalikan hasilnya, yang merupakan daftar pelanggan yang dikembalikan dari metode GetCustomers.
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;
}
}
Dalam contoh berikut, aktivitas ListCustomers mengambil daftar pelanggan, lalu aktivitas ForEach<T> menghitungnya dan menulis nama perusahaan dan nama kontak setiap pelanggan ke konsol.
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);
Ketika alur kerja ini dipanggil, data berikut ditulis ke konsol. Karena kueri ini mengembalikan banyak pelanggan, hanya sebagian output yang ditampilkan di sini.
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
...
Mengonsumsi umpan OData tanpa menggunakan pustaka klien
OData memaparkan data sebagai sumber daya yang dapat diatasi oleh URI. Saat Anda menggunakan pustaka klien, URI ini dibuat untuk Anda, tetapi Anda tidak perlu menggunakan pustaka klien. Jika diinginkan, layanan OData dapat diakses secara langsung tanpa menggunakan pustaka klien. Ketika tidak menggunakan pustaka klien, lokasi layanan dan data yang diinginkan ditentukan oleh URI dan hasilnya dikembalikan sebagai respons terhadap permintaan HTTP. Data mentah ini kemudian dapat diproses atau dimanipulasi dengan cara yang diinginkan. Salah satu cara untuk mengambil hasil kueri OData adalah dengan menggunakan kelas WebClient. Dalam contoh ini, nama kontak untuk pelanggan yang diwakili oleh kunci ALFKI diperoleh.
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}");
Ketika kode ini dijalankan, output berikut ditampilkan ke konsol:
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>
Dalam alur kerja, kode dari contoh ini dapat dimasukkan ke dalam override Execute dari aktivitas kustom berbasis CodeActivity, tetapi fungsionalitas yang sama juga dapat dicapai dengan menggunakan aktivitas InvokeMethod<TResult>. Aktivitas InvokeMethod<TResult> ini memungkinkan penulis alur kerja untuk memanggil metode statis dan instans kelas, dan juga memiliki opsi untuk memanggil metode yang ditentukan secara asinkron. Dalam contoh berikut, aktivitas InvokeMethod<TResult> dikonfigurasi untuk memanggil metode DownloadString kelas WebClient dan mengembalikan daftar pelanggan.
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
},
InvokeMethod<TResult> dapat memanggil metode statis dan instans kelas. Karena DownloadString adalah metode instans kelas WebClient, instans baru kelas WebClient ditentukan untuk TargetObject.
DownloadString ditentukan sebagai MethodName, URI yang berisi kueri ditentukan dalam koleksi Parameters, dan nilai yang dikembalikan ditetapkan ke nilai Result. Nilai RunAsynchronously diatur ke true, yang berarti bahwa pemanggilan metode akan berjalan secara asinkron sehubungan dengan alur kerja. Dalam contoh berikut, alur kerja dibangun yang menggunakan aktivitas InvokeMethod<TResult> untuk mengkueri sampel layanan data Northwind untuk daftar pesanan untuk pelanggan tertentu, lalu data yang dikembalikan ditulis ke konsol.
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);
Saat alur kerja ini dipanggil, output berikut ditampilkan ke konsol. Karena kueri ini mengembalikan beberapa pesanan, hanya sebagian output yang ditampilkan di sini.
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" />
...
Contoh ini menyediakan satu metode yang dapat digunakan penulis aplikasi alur kerja untuk menggunakan data mentah yang dikembalikan dari layanan OData. Untuk informasi selengkapnya tentang mengakses WCF Data Services menggunakan URI, lihat Mengakses Sumber Daya Data Service (WCF Data Services) dan OData: Konvensi URI.