【发布时间】:2017-06-08 22:32:13
【问题描述】:
我们最大限度地使用 postgresql 的功能来减轻我们的开发工作量。我们在 postgresql 中大量使用自定义类型(用户定义类型);我们的大多数函数和存储过程要么将它们作为输入参数,要么返回它们。
我们想从 F# 的 SqlDataProvider 中使用它们。这意味着我们应该能够以某种方式告诉 F# 如何将 F# 用户类型映射到 postgresql 用户类型。换句话说
- Postgresql 有我们定义的用户类型 post_user_defined
- F# 有我们定义的用户类型 fsharp_user_defined
我们应该指示 Npgsql 以某种方式执行此映射。到目前为止,我的研究为我指出了两种方法,但对我来说没有一个是完全清楚的。任何帮助表示赞赏
方法 1
NpgsqlTypes 命名空间具有预定义的一组 postgresql 类型映射到开箱即用的 .NET。其中很少是类,其他是结构。假设我想使用 postgresql 的内置类型点,该类型点由 Npgsql 通过 NpgsqlPoint 映射到 .NET。我可以将其映射到应用程序特定的数据结构,如下所示:
let point (x,y) = NpgsqlTypes.NpgsqlPoint(x,y)
(来自 PostgreSQLTests.fsx)
在这种情况下,已经定义了 postgresql 点和 NpgsqlPoint (.NET)。现在我想为我的自定义类型做同样的事情。
假设用户定义的postgresql组合是
create type product_t as ( name text, product_type text);
而应用程序数据结构(F#)就是记录
type product_f = {name :string; ptype :string }
或者一个元组
type product_f = string * string
当作为参数传递给 postgresql 函数/过程时,如何告诉 Npgsql 使用我的类型?看起来我需要使用没有公共构造函数的 NpgsqTypes.NpgsqlDbType.Composite 或 Npgsql.PostgresCompositeType。
我在这里是死路一条!
方法2
从this post 得到启发,我可以创建一个自定义类型并在 MapCompositeGlobally 中注册并使用它来传递给 postgresql 函数。所以,我在这里尝试一下
在Postgresql方面,类型和功能分别是
CREATE TYPE product_t AS
(name text,
product_type text)
和
func_product(p product_t) RETURNS void AS
并且来自我在 F# 中的应用程序
type PgProductType(Name:string,ProductType:string)=
member this.Name = Name
member this.ProductType = ProductType
new() = PgProductType("","")
Npgsql.NpgsqlConnection.MapCompositeGlobally<PgProductType>("product_t",null)
然后
类型提供者 = SqlDataProvider
让 ctx = Provider.GetDataContext() 让 prd = new PgProductType("F#Product","") ctx.Functions.FuncProduct.Invoke(prd);;
ctx.Functions.FuncIproduct.Invoke(prd);;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(29,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.FuncIproduct.Result.Invoke() : Unit'.
奇怪的是,错误报告是:constructor 'Invoke' 接受 0 个参数,但这里给出了 1 个。 F# 方面对 postgresql 函数所采用的参数完全视而不见。它确实承认函数 FuncIproduct 存在,但对它所接受的参数视而不见。
【问题讨论】:
标签: postgresql f# npgsql f#-data custom-type