Postgresql的FSharp数据类型提供程序



我尝试FSharp数据提供程序,但使用npgsql对抗Postgresql。我在第一线就崩溃了。

当我试图创建SqlDataConnection时,它抛出错误,消息是连接字符串不正确。

类型提供程序'Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders'报告了一个错误:不支持关键字:'端口:5432;数据库'。

现在,我使用Servicestack.Ormlite测试连接字符串和数据。它基本上使用IdbConnection。所以,连接是完全正确的。但我不知道为什么类型提供程序不起作用。

这是代码。

    //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

在上面的代码中,第一个注释行不起作用,而下面的代码使用相同的设置。这意味着问题只存在于类型提供程序,而不存在于连接IMHO。

我需要做任何其他设置吗。

如果需要任何其他详细信息,请告诉我。

更新

在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

这是网络配置

  <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>

这是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>

上面两个都有评论,另一个没有评论,两个都因不同的错误而失败。第一个是失败,错误

类型提供程序'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 server。

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

我将发布一个部分答案,希望有人能想出如何做下一步。

以下代码将编译:

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

对于通过创建的数据库testdb中的表test_table

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;

要做到这一点,你需要做四件事:

  • GAC Npgsql.dll("C:Program Files (x86)Microsoft SDKsWindowsv8.0AbinNETFX 4.0 Toolsx64gacutil.exe" /i [filename]
  • GAC Mono.Security.dll(与NuGet下载Npgsql.dll的目录相同
  • 将DbProviderFactory添加到.NET 4 64位machine.config("C:WindowsMicrosoft.NETFramework64v4.0.30319Configmachine.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>
  • 重新启动visual studio

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

这回答了你的问题;但现在是奇怪的一点,这意味着你仍然不开心。当你运行这个代码时,一旦调用dbSchema.GetDataContext(),它就会抛出一个ArgumentException,说:

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

内部异常状态

不支持"server"关键字。

带有堆栈跟踪

位于System.Data.EntityClient.EntityConnectionStringBuilder.set_Item(String关键字,Object值)位于System.Data.Common.DbConnectionStringBuilder.set_ConnectionString(字符串值)位于System.Data.EntityClient.EntityConnectionStringBuilder.ctor(字符串连接字符串)位于SqlEntityConnection1.dbSchema.GetDataContext()

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

我遇到了同样的困难。这是通过在App.config文件中添加以下内容来修复的:

<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
  <parameters>
    <parameter value="v11.0" />
  </parameters>
</defaultConnectionFactory>
<providers>
  <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
  <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, Npgsql.EntityFramework" />
</providers>

相关内容

最新更新