我正在尝试通过CRL集成创建SQL函数,但我遇到以下错误:
“GetWSClient”的CREATE FUNCTION失败,因为返回值的T-SQL和CLR类型不匹配。
我正在尝试在我的dll中使用WebService,然后将其作为SQL Server中的程序集进行集成。
我的C#代码是:
namespace InternalLists
{
public class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read, Name = "WSClient", FillRowMethodName = "Fill_WSClient",
TableDefinition = "Name nvarchar(255)")]
public static DataSet WSClient(SqlString url, SqlString idClient)
{
WSInternalList.CLIENTS client = new WSInternalList.CLIENTS();
client.Url = url.ToString();
return client.WM_CLIENT(idClient.ToString());
}
public static void Fill_WSClient(object ProductObj, out SqlString Name)
{
DataRow row = (DataRow)ProductObj;
Name = new SqlString(row["VWSDN_NAME"].ToString());
}
}
}
我的SQL代码是:
CREATE FUNCTION [dbo].[GetWSClient](@url nvarchar(255), @idClient nvarchar(255))
RETURNS TABLE (
Name nvarchar(255) NULL
)
EXTERNAL NAME [InternalLists].[InternalLists.UserDefinedFunctions].[WSClient]
GO
我已经看到this回答,但是我将我的函数声明为DataSet返回类型,并且我知道我的WS正在返回DataSet结果。
那么,我做错了什么?
答案 0 :(得分:2)
您正在创建CLR 表值函数。在http://msdn.microsoft.com/en-us/library/ms131103.aspx的文档中,这是一个示例:
using System;
using System.Data.Sql;
using Microsoft.SqlServer.Server;
using System.Collections;
using System.Data.SqlTypes;
using System.Diagnostics;
public class TabularEventLog
{
[SqlFunction(FillRowMethodName = "FillRow")]
public static IEnumerable InitMethod(String logname)
{
return new EventLog(logname).Entries;
}
public static void FillRow(Object obj, out SqlDateTime timeWritten, out SqlChars message, out SqlChars category, out long instanceId)
{
EventLogEntry eventLogEntry = (EventLogEntry)obj;
timeWritten = new SqlDateTime(eventLogEntry.TimeWritten);
message = new SqlChars(eventLogEntry.Message);
category = new SqlChars(eventLogEntry.Category);
instanceId = eventLogEntry.InstanceId;
}
}
您需要返回IEnumerable
或IEnumerable<T>
。运行时将负责枚举IEnumerable
,将每个枚举对象传递给Fill Row方法(作为上面示例中的第一个参数Object obj
)并注意将其映射到可以通过TDS喷射到客户端,客户端将根据它将其转换为结果集。
答案 1 :(得分:1)
T-SQL表数据类型与DataSet数据类型不同。 SQLCLR程序集中的UDF需要返回IEnumerable类型,而DataSet不实现IEnumerable。
您可以将函数转换为返回IListSource.GetList(),它实现了IEnumerable,如:
return ((IListSource)client.WM_CLIENT(idClient.ToString())).GetList();
标准警告适用 - 未经测试 - 但也许这会让您朝着正确的方向前进。祝福!