クライアント.NETアプリケーションでWCFデータサービス操作を消費する方法は?
-
28-09-2019 - |
質問
さて、私はいくつかのガイダンスを必死に必要とするデータサービスとLINQの新人です。ほんの数日で、私は多くの予期せぬ障害に遭遇し、今ではそれに固執しています。これらが新しいツールを学ぶことの典型的な欲求不満であることを願っています。
GPS座標のSQL Serverデータベーステーブルからデータを提供するためのWCFデータサービスがあります。特に、データのより一般的な表現を生成するために、小数の精度と緯度/経度範囲を指定できるサービス操作方法があります。
Webブラウザでは、期待どおりに機能するようです。ただし、クライアントアプリケーションから操作を呼び出すと、クライアントに返されるリストは、サービスによって生成されたリストとは異なります。
コードの一部を使用して詳細を説明します。
データサービス操作:
// This is my service operation that I need to call from my client app (see below).
// It should return an IEnumerable<Gps> (Gps is one of my Entity Model
// types) list of distinct GPS rounded to the number of decimal positions
// specified and within the range specified.
[WebGet]
public IEnumerable<Gps> GetGpsView(int decimalPlaces, decimal minLatitude, decimal minLongitude, decimal maxLatitude, decimal maxLongitude)
{
// I must first return a list of anonymous-type objects
// because LINQ does not seem to allow me to construct my
// Gps object within the query (one of those other issues
// I had to tip-toe around).
var list = (from g in this.CurrentDataSource.Gps
where g.Latitude >= minLatitude &&
g.Latitude <= maxLatitude &&
g.Longitude >= minLongitude &&
g.Longitude <= maxLongitude
select new
{
Id = 0,
Latitude = Math.Round(g.Latitude, decimalPlaces),
Longitude = Math.Round(g.Longitude, decimalPlaces)
}).Distinct().ToList();
// Now that I have my results, I need to convert the items in the
// list to my Gps entity object.
IEnumerable<Gps> gpsList = list.ConvertAll<Gps>(item => new Gps
{
Id = item.Id,
Latitude = item.Latitude,
Longitude = item.Longitude
});
return gpsList;
}
クライアントアプリから呼び出されたときに上記の方法(Visual Studioの仮想サーバーで実行する)をデバッグすると、GPSLISTはクライアントに返す直前に適切なデータが含まれているように見えます。テストパラメーターを使用して、値が指定した小数の場所に丸められている200個の異なるGPSオブジェクトのリストを取得します。
ただし、結果がクライアントアプリの呼び出し方法に返されると、200のGPSオブジェクトのリストがありますが、それらはすべて同じ値です。具体的には、重複した値は、私の期待される結果セットの最後の値です。この操作をWebブラウザで呼び出して結果を表示することでこれを確認しました。
クライアント方法:
// Partial class extension of code auto-generated by service reference.
public partial class HsiSideBySideEntities
{
public List<Gps> GetGpsView(int decimalPlaces, decimal minLatitude, decimal minLongitude, decimal maxLatitude, decimal maxLongitude)
{
this.IgnoreMissingProperties = true;
// Format my relative URI string.
string uri = string.Format("/GetGpsView?decimalPlaces={0}&minLatitude={1}M&minLongitude={2}M&maxLatitude={3}M&maxLongitude={4}M", decimalPlaces, minLatitude, minLongitude, maxLatitude, maxLongitude);
// If I debug both client and service at the same time, when I step over this
// line, it does reach my data service - and as I mentioned above, on the
// service end it appears to generate the correct results.
List<Gps> gpsList = this.Execute<Gps>(new Uri(uri, UriKind.Relative)).ToList();
// However, the results are returned to the client code, my list contains
// duplicates of the last expected record.
return gpsList;
}
}
「execute()」行の「tolist()」部分を削除しようとしましたが、デバッガーで設定された結果を表示しようとすると、「このienumerableによってサポートされている単一の列挙のみがサポートされています。 「
私が知る限り、私のクライアントコードは最初に疑わしいです。結局のところ、他のすべてのテストは、私のデータサービス操作が望ましい結果を生み出していることを示しています。
データサービスからオブジェクトのienumerableリストを取得するには、何か違うことをする必要がありますか?
CreateQuery()オプションがあることは理解していますが、execute()がこのシナリオに適したルートであることを読みました。
解決
それはおそらくこのためです:
select new
{
Id = 0,
Latitude = Math.Round(g.Latitude, decimalPlaces),
Longitude = Math.Round(g.Longitude, decimalPlaces)
}
GPSエンティティのIDプロパティがあなたの主キーであると思います。例では、返された各GPSのIDをゼロに設定しています。 WCF Data Servicesクライアントライブラリでは、同じプライマリキーを持つエンティティは、変更追跡上の理由と、.NETなどのオブジェクト指向の参照追跡環境で予想されるようにオブジェクトグラフが動作するように同じインスタンスとして扱われます。
何らかの理由でGPSエンティティに一意のIDを与えることができない場合は、主キーにGUIDを使用することを検討してください。