“地理编码”的CREATE FUNCTION失败,因为返回值的T-SQL和CLR类型不匹配

时间:2015-11-25 15:49:45

标签: c# sql sql-server geocode

我正在尝试从表中进行地理编码,并在此处找到了一个很好的示例: How to store geocoded address information into the database

或此代码

using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Data.SqlClient;
using Microsoft.SqlServer.Types;
using System.ServiceModel.Web;

namespace ProSQLSpatial
{
public partial class GoogleMaps
{
    /// <summary>
    ///
    /// </summary>
    /// <param name="address"></param>
    /// <returns></returns>
    public static GeoResponse GetGeoCodedResults(string address)
    {
        string url = string.Format(
                "http://maps.google.com/maps/api/geocode/json?address={0}&region=dk&sensor=false"

                );
        var request = (HttpWebRequest)HttpWebRequest.Create(url);
        request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
        request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(GeoResponse));
        var res = (GeoResponse)serializer.ReadObject(request.GetResponse().GetResponseStream());
        return res;
    }
}

[DataContract]
public class GeoResponse
{
    [DataMember(Name = "status")]
    public char Status { get; set; }

    [DataMember(Name = "results")]
    public CResult[] Results { get; set; }

    [DataContract]
    public class CResult
    {
        [DataMember(Name = "geometry")]
        public CGeometry Geometry { get; set; }

        [DataContract]
        public class CGeometry
        {
            [DataMember(Name = "location")]
            public CLocation Location { get; set; }

            [DataContract]
            public class CLocation
            {
                [DataMember(Name = "lat")]
                public double  Lat { get; set; }

                [DataMember(Name = "lng")]
                public double Lng { get; set; }
            }
        }
    }

    public GeoResponse()
    { }
}

我在SQL Server中创建了程序集,并尝试通过以下方式创建基于程序集的函数:

CREATE FUNCTION dbo.Geocode
    (@Address nvarchar(4000)) 
RETURNS nvarchar(4000)
AS EXTERNAL NAME [test2].[ProSQLSpatial.GoogleMaps].[GetGeoCodedResults];
GO

但我收到错误消息

  

Msg 6551,Level 16,State 2,Procedure Geocode,Line 1   “地理编码”的CREATE FUNCTION失败,因为返回值的T-SQL和CLR类型不匹配。

我已经完成了搜索,我无法弄明白。我试过更改数据类型,但仍然得到相同的消息。任何帮助都将是我的一天。感谢

1 个答案:

答案 0 :(得分:0)

这是一个适合您案例的工作示例:

C#代码(为简单起见,删除了网页内容)

using Microsoft.SqlServer.Server;
using System.Collections;
using System;

namespace ProSQLSpatial
{
    public partial class GoogleMaps
    {
        [SqlFunction(FillRowMethodName="FillRow")]
        public static IEnumerable GetGeoCodedResults(string address)
        {
            if (address == "test1")
                yield return new GeoResponse { lat = 0.1d, lng = 0.2d };
            else
                yield return new GeoResponse { lat = 0.2d, lng = 0.1d };
        }

        public static void FillRow(Object obj, out double lat, out double lng)
        {
            var entry = (GeoResponse)obj;
            lat = entry.lat;
            lng = entry.lng;
        }
    }

    public class GeoResponse
    {
        public double lat;
        public double lng;
    }
}

这里我们有SQLServer命令来注册dll和函数:

CREATE ASSEMBLY TestLib FROM 'C:\Temp\TestLib.dll'
go

CREATE FUNCTION GeoCode(@address nvarchar(4000))
RETURNS TABLE (lat float, lng float)
EXTERNAL NAME [TestLib].[ProSQLSpatial.GoogleMaps].[GetGeoCodedResults]
GO

一些测试代码,看它是否有效:

create table addresses (id int identity(1, 1) primary key, [address] nvarchar(4000))
go

insert into addresses([address]) values ('test1'), ('test2')
go

select * 
from addresses x
cross apply dbo.GeoCode(x.address)

select * from dbo.GeoCode('test1')

似乎在这里做的伎俩。