如何在客户端.NET应用程序中使用WCF数据服务操作?

如何在客户端.NET应用程序中使用WCF数据服务操作?,.net,wcf-data-services,service-operations,.net,Wcf Data Services,Service Operations,好了,各位,我是数据服务和LINQ的新手,迫切需要一些指导。在短短的几天里,我遇到了许多意想不到的障碍,现在我被困在其中。我希望这些只是学习新工具的典型挫折 我有一个WCF数据服务,用于提供来自Sql Server数据库Gps坐标表的数据。特别是,我有一个服务操作方法,允许您指定十进制精度和纬度/经度范围,以生成更通用的数据表示 在web浏览器中,它似乎可以正常工作。但是,当我尝试从客户端应用程序调用该操作时,返回给客户端的列表与服务生成的列表不同 我将使用我的代码片段来解释细节: 数据服务操作

好了,各位,我是数据服务和LINQ的新手,迫切需要一些指导。在短短的几天里,我遇到了许多意想不到的障碍,现在我被困在其中。我希望这些只是学习新工具的典型挫折

我有一个WCF数据服务,用于提供来自Sql Server数据库Gps坐标表的数据。特别是,我有一个服务操作方法,允许您指定十进制精度和纬度/经度范围,以生成更通用的数据表示

在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;
    }
// 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;
    }
}
//这是我需要从客户端应用程序调用的服务操作(请参见下文)。
//它应该返回一个IEnumerable(Gps是我的实体模型之一)
//类型)四舍五入到小数位数的不同GPS列表
//已指定并且在指定的范围内。
[WebGet]
公共IEnumerable GetGpsView(整数小数点、小数点最小纬度、小数点最小经度、小数点最大纬度、小数点最大经度)
{
//我必须首先返回匿名类型对象的列表
//因为LINQ似乎不允许我构建我的
//查询中的Gps对象(其他问题之一
//我不得不踮起脚尖)。
var list=(来自this.CurrentDataSource.Gps中的g)
其中g.纬度>=最小纬度&&
g、 纬度=经度&&
g、 新全球定位系统
{
Id=项目Id,
纬度=项目。纬度,
经度=项目。经度
});
返回gpsList;
}
如果在从客户端应用程序调用时调试上述方法(在VisualStudio的虚拟服务器上运行),则在返回客户端之前,gpsList似乎包含正确的数据。使用我的测试参数,我得到了一个200个不同Gps对象的列表,这些对象的值被舍入到我指定的小数位

然而,一旦结果返回到我的客户端应用程序中的调用方法,我就有了一个包含200个Gps对象的列表,但它们都是相同的值。具体来说,复制的值是我期望的结果集中的最后一个值。我通过在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;
    }
// 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;
    }
}
//服务引用自动生成的代码的部分类扩展。
公共部分类HsideBySideEntities
{
公共列表GetGpsView(整数小数点、小数点最小纬度、小数点最小经度、小数点最大纬度、小数点最大经度)
{
this.IgnoreMissingProperties=true;
//格式化我的相对URI字符串。
字符串uri=string.Format(“/GetGpsView?decimalPlaces={0}&minLatitude={1}M&minLatitude={2}M&maxLatitude={3}M&maxLatitude={4}M”,decimalPlaces,minLatitude,minLatitude,maxLatitude,maxLatitude,Max经度);
//如果我同时调试客户端和服务,当我跳过此步骤时
//行,它确实到达了我的数据服务-正如我上面提到的,在
//服务端它似乎生成了正确的结果。
List gpsList=this.Execute(新Uri(Uri,UriKind.Relative)).ToList();
//但是,结果将返回到客户端代码,我的列表包含
//上次预期记录的副本。
返回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为主键。

谢谢你的建议。这确实在我脑海中闪过,但我想如果是这样的话,我的列表在返回这段代码之前看起来就不正确了。但我会尝试一下,让每个人都知道结果如何。你是我今天的英雄!我没有更改您概述的代码部分,而是更改了将其从匿名类型转换为Gps对象的部分。在此之前,我声明“longid=0;”,然后在转换例程中设置“id=id++”,为每个项提供一个唯一的id值。再次感谢!