データ サービス
Silverlight 2 でデータ中心の Web アプリケーションを作成する
Shawn Wildermuth
この記事は、Silverlight 2 および ADO.NET Data Services のプレリリース版に基づいて書かれています。ここに記載されているすべての情報は、変更される場合があります。
この記事では、次の内容について説明します。
- Silverlight のデータ ソースへの接続
- ADO.NET Data Services の使用
- LINQ to SQL の使用
- サービスのデバッガ
|
この記事では、次のテクノロジを使用しています。
Silverlight 2 Beta 2、LINQ、ADO.NET Data Services
|

目次
基幹業務アプリケーションおよび他のデータ中心のアプリケーションは Silverlight™ で構築できますが、Silverlight でのデータ操作は必ずしも単純というわけではありません。Silverlight にはデータの利用や Web サービスおよび XML のサポートに必要な多数のツールが用意されていますが、これらのツールではファイアウォール越しのデータ アクセスの基本機能のみが提供されます。
一般的なデータ アクセス戦略では Web サービスとクライアント側の LINQ を組み合わせて使用しますが、これは既存の Web サービス エンドポイントを利用して Silverlight アプリケーションを強化する場合に強く推奨される方法です。しかし、特に Silverlight で動作する新しい Web サービスを作成する場合には不要なコストが生じます。
一般的な Web サービス層では従来的なデータ アクセス戦略をサーバーに実装し (カスタム ビジネス オブジェクト、LINQ to SQL、Entity Framework、NHibernate など)、Web サービスを介してデータ オブジェクトを公開します。このとき Web サービスは基になるデータ アクセス戦略へのゲートウェイにすぎません。
しかし、データに対する完全な接続を有効にするには、Web サービスのメソッドに 4 種類のデータ操作 (作成、読み取り、更新、および削除) をマップする必要があります。たとえば、Product クラスをサポートする単純なサービス コントラクトは、図 1 のようになります (記事内では C# を使用しますが、ダウンロード コードには Visual Basic® コードも含まれています)。

図 1 単純な Product Web サービス用のサービス コントラクト
[ServiceContract]
public interface ICustomerService
{
[OperationContract]
List<Product> GetAllProducts();
[OperationContract]
Product GetProduct(int productID);
[OperationContract]
List<Product> GetAllProductsWithCategories();
[OperationContract]
Product SaveProduct(Product productToSave);
[OperationContract]
void DeleteProduct(Product productToDelete);
}
アプリケーションのデータ モデル全体で動作する一連のサービスの作成には非常に時間がかかる場合があります。また、この例が示すように、機能に特化した操作では Web サービスが膨張することもあります。つまり、時間が経つにつれて Web サービスには新しい要件や操作が追加され、中には実際にコア ビジネス ドメインに属さない操作も含まれます。
たとえば、図 1 にある操作 GetAllProductsWithCategories を使用すると Product が取得され、既定でカテゴリが含まれます。この単純な例に、並べ替え、フィルタ処理、さらにはページングのメカニズムが追加されても不思議ではありません。これらのメカニズムを手動で作成するのを続ける代わりに、データ操作 (照会、並べ替え、フィルタ処理など) をサポートする単純な方法があると便利です。そこで、ADO.NET Data Services を使います。
ADO.NET Data Services
ADO.NET Data Services の目的は、データ モデルに Web アクセス可能なエンドポイントを提供することです。これらのエンドポイントではサーバーからのデータをフィルタ処理、並べ替え、整形、およびページングする手段が提供されます。開発者がこれらの機能をカスタムに構築する必要はありません。基本的に、各エンドポイントは LINQ クエリの開始点です。エンドポイントからは、実際に探しているデータを照会できます。
しかし、ADO.NET Data Services を単なる別のデータ アクセス戦略と考えることはできません。ADO.NET Data Services では直接のデータ アクセスは実行されません。これは実際、シリアル化、照会、および更新をサポートするデータ アクセス テクノロジの上に階層化されます。データの照会や更新のジョブは、この基になるデータ アクセス層に残されます。図 2 に、一般的なアプリケーション アーキテクチャでの ADO.NET Data Services とその配置を示します。
図 2 ADO.NET Data Services の層 (クリックすると拡大画像が表示されます)
ADO.NET Data Services は実際のデータ アクセス操作をデータ アクセス機能に依存しているため、この操作を指定する方法が必要になります。ADO.NET Data Services では、各サービスが LINQ 対応プロバイダによってサポートされている必要があります。実際には、各エンドポイントが IQueryable エンドポイントになります。このため、ADO.NET Data Services では IQueryable をサポートするすべてのオブジェクトがサポートされます。
サービスを作成する
プロジェクトに ADO.NET Data Services を追加すると新しい .svc ファイルが作成されますが、これはサービスを表すクラスです。Web サービスとは異なり、実際にはサービス操作を自身で実装せず、ほとんどの煩雑な処理は DataService クラスに任せます。サービスを実行するために必要ないくつかの小さいタスクがあります。まず、DataService クラスはコンテキスト オブジェクトと呼ばれる型パラメータを必要とします。コンテキスト オブジェクトはサービスとして公開されるデータを記述するクラスです。リレーショナル データベースのデータがサービスで公開される場合、このクラスは一般に Entity Framework の ObjectContext または LINQ to SQL の DataContext から派生します。
// Use my NorthwindEntities context object
// as the source of the Service's Data
public class Products : DataService<NorthwindEntities>
コンテキスト オブジェクトに基本クラスの要件はありません。実際、プロパティで IQueryable インターフェイスを実装しさえすれば独自のクラスを作成できます。ADO.NET Data Services ではこれらのプロパティがエンドポイントとして公開されます。
public class StateContext
{
StateList _states = new StateList();
public IQueryable<State> States
{
get { return _states.AsQueryable<State>(); }
}
}
InitializeService 呼び出しで渡される IDataServiceConfiguration オブジェクトを使用して、サービスで許可されるアクセス許可の種類を指定できます。ADO.NET Data Services では、図 3 に示すように、名詞と動詞の抽象化を使用してアクセス許可を指定します。

図 3 アクセス ルールの設定
// This method is called only once to initialize service-wide policies.
public static void InitializeService(IDataServiceConfiguration config)
{
// Only allow us to read or update Products Entities
// not Delete or Create
config.SetEntitySetAccessRule("Products",
EntitySetRights.AllRead |
EntitySetRights.WriteUpdate);
// Only Allow Reading of Category and Supplier Entities
config.SetEntitySetAccessRule("Categories", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("Suppliers", EntitySetRights.AllRead);
}
この処理を行うと、サービスを直接参照できます。各エンドポイントごとに Atom フィード情報が表示されます。ADO.NET Data Services のデバッグでは、Internet Explorer® の RSS フィード ビューを無効にするか、または別のブラウザを使用してサービスの XML 形式を表示することをお勧めします。
データを照会および更新する
ADO.NET Data Services ではサービスが REST (Representational State Transfer) ベースのサービスとして公開されますが、これは SOAP ベースのサービスではありません。つまり、SOAP エンベロープではなくサービスからの応答のペイロードに、要求メタデータではなくデータのみが含まれています。すべての要求は HTTP 動詞 (GET、PUT、POST など) と要求 URI の組み合わせを使用して記述されます。図 4 に示すような Products、Categories、および Suppliers を記述するモデルがあるとします。この結果生じる ADO.NET Data Services のサービスには 3 つのエンドポイントがあり、それぞれがモデルのエンティティ セットに対応します。モデルのエンティティ セットに対応する URI は単純なサービスとエンドポイント名のアドレスであり、http://localhost/{ServiceName}/{EndPointName} つまり http://localhost/Product.svc/Products のようになります。
図 4 データ モデルのサンプル (クリックすると拡大画像が表示されます)
この URI 構文では、固有のエンティティの取得、結果の並べ替え、フィルタ処理、ページング、および整形などのさまざまな機能のホストがサポートされます。
ADO.NET Data Services はこのような URL 形式のクエリを使用してサービスのコンシューマにデータを返します。現在、JSON (JavaScript Object Notation) および Atom ベースの XML という 2 つのシリアル化形式がサポートされています (将来のバージョンでは拡張される予定です)。JSON はクライアント側の Web コードで簡単に使用できる形式ですが、Atom は XML ベースの形式であり XML パーサーによるその後のサポートが必要です。
クエリでシリアル化形式の指定を要求する代わりに、ADO.NET Data Services は標準の HTTP accept ヘッダーを使用してクライアントにどちらの形式を返すかを決定します。XML が利用可能なクライアント (ブラウザなど) から要求を発行し、Accept ヘッダーで優先的な形式の種類を指定しない場合、返されるデータの既定の形式は Atom になります。
データの照会はソリューションの一部にすぎません。最終的なソリューションでは照会と更新の両方をサポートする必要があります。これらのすべての要件をサポートするため、ADO.NET Data Services では基本的な 4 つのデータ アクセス操作が基本的な 4 つの HTTP 動詞にマップされます (図 5 を参照)。

図 5 データ アクセス動詞と HTTP 動詞
| データ アクセス動詞 |
HTTP 動詞 |
| 作成 |
POST |
| 読み取り |
GET |
| 更新 |
PUT |
| 削除 |
DELETE |
これらの動詞を使用すると、ADO.NET Data Services ではサービスのコンシューマが異なる種類の特殊なエンドポイントを作成せずに、すべての種類のデータ操作を利用できます。ADO.NET Data Services で動作するデータを更新するための唯一の要件は、基になるデータ アクセス テクノロジが IUpdatable インターフェイスをサポートしていることです。このインターフェイスは ADO.NET Data Services からデータ ソースへの更新の伝達方法を定義するコントラクトです。
現在、このインターフェイスをサポートしているデータ アクセス テクノロジは Entity Framework のみです。将来的に、(LINQ to SQL、LLBGenPro、および NHibernate を含む) 多くの層でもサポートされることが期待されます。ここまでで ADO.NET Data Services が理解できたので、Silverlight 2 で使ってみることにします。
Silverlight 2.0 クライアント ライブラリ
ADO.NET Data Services で URI 構文を通じてクエリの発行とデータの更新を行い、XML を直接操作する場合に、必要な機能は実行できますが、依然として多くの機能を構築することになります。そこで、Silverlight 対応 ADO.NET Data Services クライアント ライブラリを使用します。このライブラリを (コマンドライン ツールと共に) 使用すると、Silverlight アプリケーションで LINQ クエリを直接発行することができ、クエリはクライアント ライブラリによって HTTP クエリまたはデータ サービスへの更新要求に変換されます。
開始の前に、いくつかのコードを生成する必要があります。このコード生成は ADO.NET Data Services サービスのメタデータを読み取り、サービス エンティティのデータのみのクラスと、サービス自体を表すクラスを生成します。
コードの生成には、Microsoft® .NET Framework 3.5 フォルダ (通常は c:\windows\Microsoft.NET\Framework\v3.5\) に収められている DataSvcUtil.exe ツールを使用します。以下のように、ツールを実行し、サービスの URI、出力コード ファイル、コードの作成言語を指定します。
DataSvcUtil.exe –uri:http://localhost/Product.svc –out:data.cs
–lang:CSharp
これにより、エンドポイントごとのデータ コントラクト クラスおよび DataServiceContext の派生クラスの新しいファイルが作成されます。DataServiceContext クラスはサービスのエントリ ポイントとして使用され、クエリの実行が可能なサービス エンドポイントを公開します。このクラスを Silverlight プロジェクトに追加し、System.Data.Services.Client.dll (Silverlight 2 Beta 2 SDK の一部) への参照を追加すると、ADO.NET Data Services の操作に必要なすべてのコードが揃います。
Silverlight クライアント コードは、.NET を対象とするコードで作成する他の LINQ ベースのクエリと同じです。DataServiceContext の派生クラスを作成し、そのクラスに対して LINQ クエリを発行します。以下のようになります。
// Create the Service class specifying the
// location of the ADO.NET Data Services
NorthwindEntities ctx =
new NorthwindEntities(new Uri("Products.svc", UriKind.Relative));
// Create a LINQ Query to be issued to the service
var qry = from p in ctx.Products
orderby p.ProductName
select p;
このクエリを実行すると、必要なデータを取得する Web 要求が発行されます。ただし、この Silverlight コードが標準の LINQ クエリと大きく異なる点は、Silverlight では同期 Web 要求が許可されない点です。そのため、以下のように、非同期での実行のためにまずクエリを DataServiceQuery<T> オブジェクトにキャストし、BeginExecute を明示的に呼び出して、非同期の実行を開始する必要があります。
// Cast to a DataServiceQuery<Product>
// (since the query is returning Products)
DataServiceQuery<Product> productQuery =
(DataServiceQuery<Product>)qry;
// Execute the Query Asynchronously specifying
// a callback method
productQuery.BeginExecute(new
AsyncCallback(OnLoadComplete),
productQuery);
クエリが実行されると (操作の成功または失敗にかかわらず)、AsyncCallback に指定されたメソッドが実行されます。ここには、実際の結果を処理する LINQ クエリを列挙できます。一般には、図 6 のように、AsyncCallback に元のクエリを含めると、コールバック メソッドで取得できます (またはクラスの一部として保存できます)。

図 6 コレクションに結果を追加する
void OnLoadComplete(IAsyncResult result)
{
// Get a reference to the Query
DataServiceQuery<Product> productQuery =
(DataServiceQuery<Product>)result.AsyncState;
try
{
// Get the results and add them to the collection
List<Product> products = productQuery.EndExecute(result).ToList();
}
catch (Exception ex)
{
if (HtmlPage.IsEnabled)
{
HtmlPage.Window.Alert("Failed to retrieve data: " + ex.ToString());
}
}
}
これまで LINQ を使ったことがない読者には、このパターンはきわめてなじみの浅い方法です。現時点では非同期パッケージ (ThreadPool や BackgroundWorker など) で LINQ を実行する以外に、非同期 LINQ の優れたパターンはありません。Silverlight ではすべての要求が非同期であることが要求されるため、ADO.NET Data Services クライアント ライブラリを使用するにはこのパターンが必要になります。
関連エンティティを読み込む
ADO.NET Data Services では、関連エンティティを読み込む方法を選択することも可能です。前述の例では、サーバーから製品を読み込んでいました。それぞれの製品は、製品のカテゴリおよび製品のサプライヤとの関係を保持しています。
前に使用した LINQ クエリでは、製品のみを取得していました。サプライヤまたはカテゴリ情報を表示する必要があっても、この情報は直ちにアクセスできる状態にありませんでした。この情報を必要に応じて読み込むか、または、サーバーへの元のクエリで明示的に取得する必要がありました。どちらの方法にも利点はありますが、すべてのオブジェクトの情報が必要になるとわかっている場合、通常は明示的な読み込みの方がはるかに効率的です。いくつかのエンティティのデータのみを読み込む場合は、オンデマンドの取得の方が適しています。
既定では、関係プロパティ (Product.Supplier など) がある場合は、プロパティを明示的に読み込まないとそのプロパティは null になります。オンデマンドの読み込みを簡素化するため、DataServiceContext クラスには BeginLoadProperty メソッド (同じ非同期モデルに従います) が用意されており、以下のようにソース エンティティ、プロパティ名、およびコールバックを指定します。
public void LoadSupplierAsync(Product theProduct)
{
TheContext.BeginLoadProperty(theProduct,
"Supplier",
new AsyncCallback(SupplierLoadComplete),
null);
}
public void SupplierLoadComplete(IAsyncResult result)
{
TheContext.EndLoadProperty(result);
}
EndLoadProperty が呼び出されると、プロパティが関連エンティティで正しく読み込まれています。多くの場合、これらの読み込みを元のクエリで明示的に行う必要があります。これを簡素化するため、LINQ プロバイダでは Expand 拡張メソッドがサポートされています。このメソッドでは、クエリの実行時に読み込むプロパティ パス名を指定できます。Expand 拡張メソッドは LINQ クエリの From 句で使用され、これらの関連エンティティの読み込みを試みるようプロバイダに通知します。たとえば、Category と Supplier の両方で Expand メソッドを使用するように元のクエリを変更すると、元のクエリの実行時にオブジェクトによってこれらの関連エンティティが読み込まれます。
var qry =
from p in TheContext.Products.Expand("Supplier").Expand("Category")
orderby p.ProductName
select p;
ADO.NET Data Services からデータを読み取るだけであれば、これで作業は完了です。クエリの作成、実行、および関連エンティティの読み込み方法を知っているだけで十分です。実際にデータを変更する場合は、若干の追加作業を行います。新しいデータを Silverlight コントロールにバインドすれば完成です。
変更管理
ADO.NET Data Services クライアント ライブラリではオブジェクトの自動的な変更の監視がサポートされていません。したがって、オブジェクト、コレクション、および関係が変更された場合にこれらの変更を DataServiceContext オブジェクトに通知するのは開発者に一任されます。DataServiceContext オブジェクトへの通知 API はかなり単純です。図 7 にこれらを示します。

図 7 DataServiceContext の変更 API
| メソッド |
説明 |
| AddObject |
新規作成されたオブジェクトを追加します。 |
| UpdateObject |
オブジェクトの変更をマークします。 |
| DeleteObject |
削除するオブジェクトをマークします。 |
| AddLink |
2 つのオブジェクト間のリンクを追加します。 |
| UpdateLink |
2 つのオブジェクト間のリンクを更新します。 |
| DeleteLink |
2 つのオブジェクト間のリンクを削除します。 |
つまり、オブジェクトへの変更を監視し、独自のコードで DataServiceContext オブジェクトに通知する必要があります。自動的な変更管理が存在しないことは一見残念なことのようですが、これが効率的で小さいライブラリを実現しています。
オブジェクトに対する変更をどのように監視するのか気になる読者もいるかもしれません。その答えは生成されたコードです。生成された各データ コントラクト クラスには、クラスのデータの変更時に呼び出される部分メソッドがあります (部分メソッドの詳細については、
go.microsoft.com/fwlink/?LinkId=122979 を参照してください)。これらのメソッドを実装しない場合、クラスではこの変更通知によるオーバーヘッドが生じません。変更をサポートする任意のデータ コントラクトに対して部分メソッド メカニズムを使用して、変更通知を実装できます。部分メソッドで DataServiceContract を呼び出すだけでよく、DataServiceContract クラスの結合は必要ありません。
さいわい、Silverlight では変更通知用のインターフェイス (INotifyPropertyChange) が既にサポートされています。データが変更されたことを必要な対象に通知するには、実装でこのインターフェイスを利用します。たとえば、データ コントラクト クラス (この場合は Product クラス) で INotifyPropertyChange を実装して、オブジェクトの変更時に起動されるイベントを定義できます。このコードを次に示します。
public partial class Product : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
}
この実装によって、プロパティの変更時にイベントを発生させることができます。生成されたデータ コントラクト クラスで呼び出される部分メソッドを実装することで、このイベントを発生させるタイミングを決定できます。たとえば、ProductName プロパティの変更をサブスクライバに通知するには、OnProductNameChanged 部分メソッドを実装し、変更されたプロパティをイベント サブスクライバに特定する ProductName を渡して、PropertyChanged イベントを起動するだけです。このコードを次に示します。
partial void OnProductNameChanged()
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ProductName"));
}
}
書き込み可能なすべてのプロパティに対しこれらの部分メソッドを実装することで、オブジェクトに対する変更を簡単に監視できます。次に、PropertyChanged イベントに登録し、オブジェクトの変更を DataServiceContext オブジェクトに通知できます。
// In the OnLoadComplete method
// Get the results and add them to the collection
List<Product> products = productQuery.EndExecute(result).ToList();
foreach (Product product in products)
{
// Wireup Change Notification
product.PropertyChanged +=
new PropertyChangedEventHandler(product_PropertyChanged);
}
最後に、DataServiceContext オブジェクトに通知する product_PropertyChanged メソッドを実装できます。
void product_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Product product = (Product)sender;
TheContext.UpdateObject(product);
}
同様に、図 8 に示すように、オブジェクトが作成または削除されたときは DataServiceContext に通知する必要があります。

図 8 作成および削除の通知
void addNewButton_Click(object sender, RoutedEventArgs e)
{
Product theProduct = new Product();
// ...
TheContext.AddObject(theProduct);
}
void deleteButton_Click(object sender, RoutedEventArgs e)
{
Product theProduct = (Product)theList.SelectItem;
TheContext.DeleteObject(theProduct);
theCollection.Remove(theProduct);
}
これらのすべてのコードが作成できたら、Silverlight UI でオブジェクトを変更し、データ バインドと変更通知のコードを通じて、DataServiceContext が行われた変更を確実に認識するようにできます。では、実際のサービスの更新はどのように実行するのでしょうか。
サービスを通じて更新する
DataServiceContext オブジェクトがデータの変更を認識するようになったので、それらの変更をサーバーに通知する手段が必要です。DataServiceContext クラスには、これに役立つ BeginSaveChanges メソッドが用意されています。このメソッドは、この記事で前述したクエリと同じ非同期モデルに従います。BeginSaveChanges メソッドは、以下に示すように、DataServiceContext のすべての変更を認識し、サーバーに送信します。
TheContext.BeginSaveChanges(SaveChangesOptions.None,
new AsyncCallback(OnSaveAllComplete),
null);
BeginSaveChanges の発行時は、SaveChangesOptions というフラグ付き列挙体があります。この列挙体を使用して、バッチ処理を行うかどうか、および保存に失敗したオブジェクトがあっても続行するかどうかの 2 つのオプションを指定できます。通常は、常にバッチ処理を行うことをお勧めします。実際、サーバーで参照の整合性に特定の制約がある場合、一部の種類の親子関係では正常な更新のためにバッチ処理が要求されます。
保存が完了するとコールバックが実行されます。2 つのメカニズムによって、エラー情報が自動で伝達されます。まず、保存の実行時に例外がスローされると、コールバックで "EndSaveChanges" を呼び出したときにこの例外がスローされます。したがって、try/catch ブロックを使用して致命的なエラーをキャッチする必要があります。さらに、EndSaveChanges からの戻り値の型は DataServiceResponse オブジェクトです。DataServiceResponse には HasErrors プロパティ (図 9 を参照) がありますが、Silverlight 2 Beta 2 Version のライブラリではこの値は信頼できません。

図 9 BeginSaveChanges コールバック
void OnSaveAllComplete(IAsyncResult result)
{
bool succeeded = true;
try
{
DataServiceResponse response =
(DataServiceResponse)TheContext.EndSaveChanges(result);
foreach (OperationResponse opResponse in response)
{
if (opResponse.HasErrors)
{
succeeded = false;
}
}
}
catch (Exception ex)
{
succeeded = false;
}
// Alert the User
}
この値に依存する代わりに、実際の OperationResponse オブジェクト (DataServiceResponse は OperationResponse オブジェクトのコレクションです) を反復処理して、サーバーから返されるそれぞれの応答にエラーがあるかどうかをチェックできます。今後のバージョンでは、DataServiceResponse クラス自体の HasErrors プロパティを信頼できるはずです。
サービスをデバックする
サービスのデバッグでは、3 つの重要な処理を実行する必要があります。それらの処理とは、DataServiceContext オブジェクトのデータの状態の表示、ADO.NET Data Services による要求の表示、およびサーバー エラーのキャッチです。
最初に、DataServiceContext オブジェクトのエンティティの状態について説明しましょう。DataServiceContext クラスは Entities と Links という 2 つの便利なコレクションを公開します。これらのコレクションは、DataServiceContext が追跡するエンティティおよびエンティティ間のリンクの読み取り専用コレクションです。デバッグ時は、オブジェクトの変更をマークしているかどうかにかかわらず、変更追跡コードが正常に動作しているかどうかを判断するために、デバッガでこれらのコレクションを表示することが非常に役立ちます。
また、Silverlight 2 アプリケーションで行われている実際のサーバー要求を表示することも重要です。何らかの種類のネットワーク プロキシを使用するのが最善の方法です。筆者は Fiddler2 (
fiddler2.com) を使用しています。Fiddler2 になじみのない読者のために説明すると、これは基本的に Web トラフィックの監視ツールであり、実際の通信内容を見ることができます。
ADO.NET Data Services の場合、実際の通信内容を見て Silverlight アプリケーションとの間で何が送受信されているかをチェックする必要があります。詳細については、筆者のブログ (
wildermuth.com/2008/06/07/Debugging_ADO_NET_Data_Services_with_Fiddler2) を参照してください。
最後に、最新の .NET Framework 3.5 SP1 ではサーバー側のエラーがクライアントに有効に伝達されていません。実際、サーバーのほとんどのエラーはサーバーにより抑えられています。サーバー エラーをデバッグする最善の方法は、[デバッグ] メニューの [例外] オプション ([デバッグ] -> [例外]) を使用して、すべての .NET 例外で停止するようにデバッガを構成することです。このオプションを選択すると、サービスでスローされた例外を表示できます (ただし、他の初回の例外を通じて "続行" する必要がある場合があります)。
まとめ
この記事の目的は、ADO.NET Data Services が Silverlight 2 とサーバー ベースのモデルの間のゲートウェイとなるしくみを示すことです。手動で設計した Web サービスに頼らずに、ADO.NET Data Services を使用してサーバーのデータの読み取りおよび書き込みを行う方法が理解できたはずです。ご覧のように、Silverlight、ADO.NET Data Services、および LINQ を組み合わせて使用すると、Web 2.0 テクノロジのあらゆる利点を利用して強力なデータ駆動型 Web アプリケーションを構築できます。これらのテクノロジの詳細については、「参考資料」を参照してください。