CLR表值函数FillRow方法参数数量不匹配错误排查
问题根源
你错误地将返回IEnumerable的主函数指定为FillRowMethodName的目标方法。SQL Server要求CLR表值函数必须包含两个核心部分:
- 主函数:负责生成要返回的数据集(返回
IEnumerable类型) - FillRow方法:负责将
IEnumerable中的每个对象拆解为SQL表的列,它的参数数量必须等于表列数 + 1(多出来的参数是要拆解的对象实例)
你的代码把主函数当成了FillRow方法,导致签名不匹配,触发了错误提示。
修正后的C#代码
首先补全TraceContents类定义(原代码未给出,必须包含才能编译),然后添加符合要求的FillRow方法,并修正主函数的SqlFunction属性:
// 补全TraceContents类,对应输出表的结构 public class TraceContents { public string Site { get; set; } public short Line { get; set; } public string Shift { get; set; } public DateTime ProductionDate { get; set; } public string ProductionTime { get; set; } public string DayName { get; set; } public bool Perfect_Trace { get; set; } public bool NWFGenerated_Trace { get; set; } public bool Altered_Trace { get; set; } } public partial class UserDefinedFunctions { // 主函数:负责生成数据,FillRowMethodName指向专门的FillRow方法 [SqlFunction(DataAccess = DataAccessKind.Read, FillRowMethodName = "Fill_Read_TraceRow", // 修正为正确的FillRow方法名 TableDefinition = " Site NVARCHAR(3)" + ",Line TINYINT" + ",Shift NVARCHAR(2)" + ",ProductionDate DATETIME2(0)" + ",ProductionTime NVARCHAR(5)" + ",DayName NVARCHAR(9)" + ",Perfect_Trace BIT" + ",NWFGenerated_Trace BIT" + ",Altered_Trace BIT")] public static IEnumerable Read_Trace([SqlFacet(MaxSize = 255)] SqlChars customer, [SqlFacet(MaxSize = 255)] SqlChars trace) { var trc = trace.ToString(); RegexList regexList = GetRegexList(customer.ToString(), trc); return new List<TraceContents> { new TraceContents { Site = GetValue(regexList.Site_Regex, trc), Line = short.Parse(new string(GetValue(regexList.Line_Regex, trc).Where(char.IsNumber).ToArray())), Shift = GetValue(regexList.Shift_Regex, trc), ProductionDate = JulianToDate(GetValue(regexList.Date_Regex, trc)), ProductionTime = GetValue(regexList.Time_Regex, trc), DayName = GetValue(regexList.Day_Regex, trc), Perfect_Trace = regexList.Perfect_Trace, NWFGenerated_Trace = regexList.NWFGenerated_Trace, Altered_Trace = regexList.Altered_Trace } }; } // 新增FillRow方法:参数1是TraceContents实例,后续参数对应表的每一列(out修饰) public static void Fill_Read_TraceRow(object rowObj, out SqlString Site, out SqlByte Line, out SqlString Shift, out SqlDateTimeOffset ProductionDate, out SqlString ProductionTime, out SqlString DayName, out SqlBoolean Perfect_Trace, out SqlBoolean NWFGenerated_Trace, out SqlBoolean Altered_Trace) { TraceContents row = (TraceContents)rowObj; Site = string.IsNullOrEmpty(row.Site) ? SqlString.Null : new SqlString(row.Site); Line = new SqlByte((byte)row.Line); Shift = string.IsNullOrEmpty(row.Shift) ? SqlString.Null : new SqlString(row.Shift); ProductionDate = new SqlDateTimeOffset(row.ProductionDate); ProductionTime = string.IsNullOrEmpty(row.ProductionTime) ? SqlString.Null : new SqlString(row.ProductionTime); DayName = string.IsNullOrEmpty(row.DayName) ? SqlString.Null : new SqlString(row.DayName); Perfect_Trace = row.Perfect_Trace; NWFGenerated_Trace = row.NWFGenerated_Trace; Altered_Trace = row.Altered_Trace; } // 保留你原有的GetValue、GetRegexList、JulianToDate方法 private static string GetValue(Regex regex, string input) => /* 你的原有实现 */; private static RegexList GetRegexList(string customer, string trace) => /* 你的原有实现 */; private static DateTime JulianToDate(string julianDate) => /* 你的原有实现 */; } // 补全RegexList类定义 public class RegexList { public Regex Site_Regex { get; set; } public Regex Line_Regex { get; set; } public Regex Shift_Regex { get; set; } public Regex Date_Regex { get; set; } public Regex Time_Regex { get; set; } public Regex Day_Regex { get; set; } public bool Perfect_Trace { get; set; } public bool NWFGenerated_Trace { get; set; } public bool Altered_Trace { get; set; } }
关键说明
- FillRow方法签名要求:
- 第一个参数必须是
object类型(对应IEnumerable中的元素,后续强制转换为实际类型) - 后续每个参数对应SQL表的一列,必须用
out修饰,类型要匹配SQL类型的CLR映射(比如SQL的TINYINT对应SqlByte,BIT对应SqlBoolean) - 参数总数 = 表列数 + 1(这就是错误提示中“多1个参数”的原因)
- 第一个参数必须是
- 主函数与FillRow的关联:通过
SqlFunction属性的FillRowMethodName指定FillRow方法的名称,两者必须在同一个类中 - 空值处理:在FillRow方法中要处理.NET空值,转换为SQL对应的
Sql*Null值,避免返回无效数据
后续操作
- 用修正后的代码重新编译生成
Functions.dll - 重新执行你原有的SQL脚本(无需修改SQL部分)
内容的提问来源于stack exchange,提问作者High Plains Grifter
相关产品推荐
相关产品推荐

