Postgresql的FSharp数据类型提供程序

kun*_*jee 8 postgresql f# npgsql type-providers f#-3.0

我正在尝试FSharp数据提供程序,但使用npgsql对Postgresql.我在第一线被击败了.

当我尝试创建SqlDataConnection时,它会抛出错误,并显示连接字符串不正确的消息.

类型提供程序'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders'报告错误:不支持关键字:'port:5432; database'.

现在,我使用Servicestack.Ormlite测试连接字符串和数据.这基本上使用IdbConnection.所以,连接都是正确的.但我不知道为什么Type Provider不工作.

这是代码.

    //type dbSchema = SqlDataConnection<ConnectionString = "Server=localhost;Port=5432; Database=TestDB;User Id=postgres;Password=g00gle*92;" >
[<CLIMutable>]
type Person = 
    { ID : int;
      FirstName : string;
      LastName : string }

[<EntryPoint>]
let main args = 
    let dbFactory = 
        OrmLiteConnectionFactory
            (
             "Server=localhost;Port=5432; Database=TestDB;User Id=postgres;Password=*****;", 
             PostgreSqlDialect.Provider)
    use dbConnection = dbFactory.OpenDbConnection()
    Console.WriteLine dbConnection.State
    let persons = dbConnection.Select<Person>()
    persons.ForEach(fun p -> Console.WriteLine p.FirstName)
    Console.Read() |> ignore
    0
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,第一个注释行无效,而下面的代码设置相同.这意味着问题只与类型提供者没有连接IMHO.

我是否需要进行任何其他设置.

如果需要任何其他细节,请告诉我.

UPDATE

在kvb的评论之后,我试过了两个.这是使用web配置更新的代码.

//type dbSchema = SqlEntityConnection<ConnectionStringName = "TestDB", Provider="Npgsql">
    type dbSchema = SqlEntityConnection< ConnectionStringName="TestDB" >

    [<CLIMutable>]
    type Person = 
        { ID : int;
          FirstName : string;
          LastName : string }

    [<EntryPoint>]
    let main args = 
        let dbFactory = 
            OrmLiteConnectionFactory
                (
                 "Server=localhost;Port=5432; Database=TestDB;User Id=postgres;Password=*******;", 
                 PostgreSqlDialect.Provider)
        use dbConnection = dbFactory.OpenDbConnection()
        Console.WriteLine dbConnection.State
        let persons = dbConnection.Select<Person>()
        persons.ForEach(fun p -> Console.WriteLine p.FirstName)
        Console.Read() |> ignore
        0
Run Code Online (Sandbox Code Playgroud)

这是web配置

  <system.data>
    <DbProviderFactories>
      <add name="Npgsql Data Provider"
            invariant="Npgsql"
            description="Data Provider for PostgreSQL"
            type="Npgsql.NpgsqlFactory, Npgsql" />
    </DbProviderFactories>
  </system.data>
  <connectionStrings>
    <add name="TestDB"
          connectionString="Server=localhost:5432; Database=TestDB;User Id=postgres;Password=******;"
          providerName="Npgsql" />

  </connectionStrings>
Run Code Online (Sandbox Code Playgroud)

这是在appconfig中的程序集.我认为它不会出现在GAC中,因为我是通过nuget添加的

 <dependentAssembly>
    <assemblyIdentity name="Npgsql" publicKeyToken="5d8b90d52f46fda7" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-2.0.12.0" newVersion="2.0.12.0" />
 </dependentAssembly>
Run Code Online (Sandbox Code Playgroud)

上面两个都被评论,另一个没有被评论,两个都失败了不同的错误.第一个是失败的错误

类型提供程序'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders'报告错误:读取架构时出错.错误7001:在配置中找不到指定的存储提供程序"Npgsql",或者"Npgsql"无效.无法找到请求的.Net Framework数据提供程序.它可能没有安装.

第二个是这个错误

类型提供程序'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders'报告错误:读取架构时出错.错误7001:提供程序未返回ProviderManifestToken字符串.建立与SQL Server的连接时发生与网络相关或特定于实例的错误.服务器未找到或无法访问.验证实例名称是否正确,以及SQL Server是否配置为允许远程连接.(提供程序:命名管道提供程序,错误:40 - 无法打开与SQL Server的连接)找不到网络路径

我仍然不明白它为什么要搜索SQL服务器.

如果需要进一步的信息,请告诉我.

bri*_*ler 4

我将发布部分答案,希望有人能够弄清楚下一步如何做。

以下代码将编译:

open Microsoft.FSharp.Data.TypeProviders
open System.Data.Entity // this is important -- you cannot see any tables without it

type internal dbSchema = 
    SqlEntityConnection<
        ConnectionString="Server=localhost;Database=testdb;User Id=postgres;Password=password;", 
        Provider="Npgsql">

[<EntryPoint>]
let main argv = 
    let context = dbSchema.GetDataContext()
    query { for item in context.test_table do
            select item }
    |> Seq.iter (fun item -> printfn "%A" item)
    0
Run Code Online (Sandbox Code Playgroud)

对于通过以下方式创建的test_table数据库中的表testdb

CREATE TABLE test_table
(
  id integer NOT NULL,
  value text,
  CONSTRAINT "PK_test_x_Id" PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE test_table
  OWNER TO postgres;
Run Code Online (Sandbox Code Playgroud)

为此,您需要做四件事:

  • GAC Npgsql.dll ( "C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\x64\gacutil.exe" /i [filename])
  • GAC Mono.Security.dll(与 NuGet 下载的 Npgsql.dll 位于同一目录中)
  • 将 DbProviderFactory 添加到您的 .NET 4 64 位 machine.config ( "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config"):这与您的 app.config 中的内容相同,但添加到 machine.config 中的相应部分,我的目前有一个Microsoft SQL Server Compact Data Provider. 请记住包含正确的公钥令牌。
<system.data>
  <DbProviderFactories>
    <add name="Npgsql Data Provider"
      invariant="Npgsql"
      description="Data Provider for PostgreSQL"
      type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
</DbProviderFactories>
</system.data>
Run Code Online (Sandbox Code Playgroud)
  • 重新启动视觉工作室。

现在SqlEntityConnection在设计时进行编译,您将能够看到所有可用的表。这也将愉快地编译成可执行文件。

这回答了你的问题;但现在有点奇怪,这意味着你仍然不高兴。ArgumentException当您运行此代码时,一旦被调用,它就会抛出一个dbSchema.GetDataContext()错误消息:

提供的连接字符串应该是特定于提供程序的有效连接字符串或 EntityClient 接受的有效连接字符串。

内部异常状态

不支持“服务器”关键字。

带堆栈跟踪

在 System.Data.EntityClient.EntityConnectionStringBuilder.set_Item(字符串关键字,对象值) 在 System.Data.Common.DbConnectionStringBuilder.set_ConnectionString(字符串值) 在 System.Data.EntityClient.EntityConnectionStringBuilder..ctor(字符串连接字符串) 在 SqlEntityConnection1.dbSchema .GetDataContext()

我尝试过修改连接字符串以使其正常工作,但我认为这一定是提供程序在运行时与设计时创建连接字符串的方式中的错误。由于此代码被发送到动态程序集中,因此如何查看代码以了解发生了什么并不明显。