使用F#中的Npgsql与postgresql存储过程之间的数组参数

时间:2017-06-08 06:40:26

标签: arrays postgresql f# npgsql f#-data

我在postgresql中有两个SQL函数(过程)。他们拿走并返回阵列;他们的签名是

create function arr_ret( x int) returns int[] as

create function arr_param( x int[] ) returns int as

执行时的第一个函数返回

> ctx.Functions.ArrRet.Invoke(6);;
Executing SQL : EXEC arr_ret(6) - params
val it : Unit = ()

>

可以看出,调用操作的签名是Unit()=();没有任何回报。我原本期望Unit()= int list,因为期望该过程返回一个整数数组。

执行时的第二个功能

> ctx.Functions.ArrParam.Invoke( [1;2;3;4;5;6] );;
  ctx.Functions.ArrParam.Invoke( [1;2;3;4;5;6] );;
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

stdin(22,1): error FS0501: The member or object constructor 'Invoke' takes 0 argument(s) but is here given 1. The requir
ed signature is 'SqlDataProvider<...>.dataContext.Functions.ArrParam.Result.Invoke() : SqlDataProvider<...>.dataContext.
Functions.ArrParam.Result.SprocResult'.

Npgsql没有看到数组类型的参数(输入或输出)。文档说3.0g版本支持postgresql数组和复合类型,我使用的是最新的3.2.3

1 个答案:

答案 0 :(得分:1)

您正在将一个类型为FSharpList的参数发送到需要params的方法中。您使用它的方式将整个列表作为单个参数发送。

ctx.Functions.ArrParam.Invoke(1, 2, 3, 4, 5, 6);;

以上将根据需要单独发送,但如果您通过整个集合则不会。原因是类型提供程序正在尝试解析对象的类型,而不是将整个数组视为多个参数。 在C#中,这样可以正常工作,但不能在F#中工作。

这是一种很好的测试方法。

在C#中定义此方法:

public static void PrintArgs(params object[] args)
{
  foreach (var arg in args)
  {
        Console.WriteLine($"Type: {arg.GetType().Name}");
  }
}

在F#中将其称为:

PrintArgs(1, 2.0, true, "4")

PrintArgs([1; 2; 3; 4])

他们导致:

> 
Type: Int32
Type: Double
Type: Boolean
Type: String
val it : unit = ()

> 
Type: FSharpList`1
val it : unit = ()

> 

你的问题是在第二次调用中发生的事情,它实际上是一个正在发送的List而不是多个参数。