【问题标题】:User defined postgresql types using Npgsql from F#使用 F# 中的 Npgsql 的用户定义的 postgresql 类型
【发布时间】:2017-06-08 22:32:13
【问题描述】:

我们最大限度地使用 postgresql 的功能来减轻我们的开发工作量。我们在 postgresql 中大量使用自定义类型(用户定义类型);我们的大多数函数和存储过程要么将它们作为输入参数,要么返回它们。

我们想从 F# 的 SqlDataProvider 中使用它们。这意味着我们应该能够以某种方式告诉 F# 如何将 F# 用户类型映射到 postgresql 用户类型。换句话说

  1. Postgresql 有我们定义的用户类型 post_user_defined
  2. 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


    【解决方案1】:

    关于您的第一种方法,正如您所了解的那样,NpgsqlTypes 包含一些 Npgsql 开箱即用支持的类型 - 但这些只是 PostgreSQL 内置类型。你不能在不改变 Npgsql 的源代码的情况下添加新类型,这不是你想做的事情。

    此外,您应该了解用户定义类型(PostgreSQL 称之为“复合”)和完全独立的类型(例如 point)之间的区别。后者是完整类型(类似于int4),具有自己的自定义二进制表示,而前者不是。

    您的第二种方法是正确的——Npgsql 完全支持 PostgreSQL 复合类型。我不知道 SqlDataProvider 是如何工作的——我假设这是一个特定于 F# 的类型提供程序——但是一旦你通过 MapCompositeGlobally 正确映射了你的复合,Npgsql 允许你通过将 NpgsqlParameter 的值设置为 PgProductType 的实例来透明地编写它.首先尝试让它与类型提供程序一起工作可能是值得的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多