Поставщик типов данных FSharp для Postgresql

Я пробовал поставщика данных FSharp, но против Postgresql, используя npgsql. И я вылетел на самой первой строчке.

Когда я пытаюсь создать SqlDataConnection, он выдает ошибку с сообщением, что строка подключения неверна.

Поставщик типа «Microsoft.FSharp.Data.TypeProviders.DesignTime.DataProviders» сообщил об ошибке: ключевое слово не поддерживается: «порт: 5432; база данных».

Теперь я проверяю строку подключения, а также данные с помощью 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

В приведенном выше коде первая прокомментированная строка не работает, в то время как с теми же настройками ниже работает код. Это означает, что проблема связана только с поставщиком типов, а не с соединениями IMHO.

Нужно ли мне делать какие-то другие настройки.

Пожалуйста, дайте мне знать, если требуются какие-либо другие подробности.

ОБНОВЛЕНИЕ

После комментария kvb я попробовал оба. Вот обновленный код с веб-конфигурацией.

//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-сервер.

Пожалуйста, дайте мне знать, если потребуется дополнительная информация.


person kunjee    schedule 25.07.2013    source источник
comment
Кажется странным, что у вас есть Port:5432, но все остальные значения находятся в форме key=value   -  person John Palmer    schedule 25.07.2013
comment
@JohnPalmer благодарит за указание на опечатку. Это дает ту же проблему. И если я попробовал localhost: 5432 напрямую, он все равно не смог подключиться к серверу.   -  person kunjee    schedule 25.07.2013
comment
SqlDataConnection полагается на sqlmetal.exe для своего кодогенератора, который поддерживает только SQL Server, насколько мне известно.   -  person kvb    schedule 25.07.2013
comment
@kvb, тогда что мне делать, чтобы добавить другую базу данных?   -  person kunjee    schedule 25.07.2013
comment
Вместо этого вы можете попробовать использовать SqlEntityConnection, поскольку Entity Framework поддерживает несколько баз данных. Я не знаю, как его настроить, но см. Также stackoverflow.com / questions / 1211475 / entity-framework-postgresql для получения дополнительной информации об использовании PostgreSQL с Entity Framework.   -  person kvb    schedule 25.07.2013
comment
@kvb сделал это ... Все еще не работает. Тем не менее, он пытается найти поставщика SQL-сервера. Не знаю почему. Я указываю поставщика Postgres в строке подключения.   -  person kunjee    schedule 25.07.2013
comment
Я думаю, вам, вероятно, нужно установить статический параметр поставщика типа Provider на имя класса поставщика Postgres. Например. для SQL Server это "System.Data.SqlClient", но соответствующий провайдер Postgres, вероятно, будет зависеть от того, какую библиотеку вы используете.   -  person kvb    schedule 25.07.2013
comment
@kvb, который я сделал в App.Config и в приведенном выше коде вместо строки подключения, я просто указываю имя строки подключения. Итак, это тоже принимает провайдер. Но до сих пор не повезло. Вы думаете, что нужно все вместе создать нового поставщика данных ???   -  person kunjee    schedule 25.07.2013
comment
Я думаю, что вам может потребоваться установить необязательный параметр Provider в _2 _ в дополнение к правильной настройке строки подключения.   -  person kvb    schedule 26.07.2013
comment
То есть SqlEntityConnection<ConnectionStringName="...", Provider="...">   -  person kvb    schedule 26.07.2013
comment
@kvb Я обновил вопрос. Я попробовал ваши предложения, но все равно не повезло.   -  person kunjee    schedule 26.07.2013
comment
Я подозреваю, что он ищет SQL Server, потому что поставщиком по умолчанию является "System.Data.SqlClient", если не указано иное. Можете ли вы опубликовать фактическую ошибку, возникающую при попытке указать "Npgsql" провайдера?   -  person kvb    schedule 26.07.2013
comment
@kvb Я обновил вопрос с сообщением об ошибке.   -  person kunjee    schedule 26.07.2013
comment
Находится ли Npgsql сборка в GAC? Что произойдет, если вы укажете полное имя сборки в разделе type (включая открытый ключ и т. Д.)?   -  person kvb    schedule 26.07.2013
comment
@kvb Я не думаю, что это там есть. Как я добавил через nuget. Спасибо, что указали, что у меня тоже есть вопрос об обновлении. Вы хотите, чтобы я изменил раздел типа, так как там только зависимая сборка. И простой NgplSQLConnection работает.   -  person kunjee    schedule 26.07.2013
comment
Я бы предложил добавить его в GAC и посмотреть, изменится ли это что-нибудь. После этого у меня заканчиваются идеи ...   -  person kvb    schedule 26.07.2013
comment
@kvb :( не повезло. Та же ошибка. В любом случае спасибо за помощь.   -  person kunjee    schedule 26.07.2013
comment
Тогда я понимаю, что он не будет работать с MySQL или любой другой базой данных, отличной от Sql Server - может быть, с Mono? Обычно они на шаг или 2 отстают от M $ последнего и самого большого.   -  person virtualeyes    schedule 29.07.2013
comment
Вы нашли решение? У меня точно такая же проблема.   -  person user1888014    schedule 30.07.2013
comment
@ user1888014 не у поставщика типа данных. Я буду использовать dapper than. Я думаю, что мне придется подождать или создать собственный поставщик типов для поддержки других баз данных. Посмотрим. В настоящее время я возвращаюсь к использованию Micro Orms.   -  person kunjee    schedule 30.07.2013


Ответы (2)


Я собираюсь опубликовать частичный ответ в надежде, что кто-нибудь придумает, как сделать следующий шаг.

Следующий код будет компилироваться:

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

Для таблицы 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;

Для этого вам нужно сделать четыре вещи:

  • 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 (в том же каталоге, в который Npgsql.dll был загружен NuGet
  • Добавьте DbProviderFactory на свой 64-битный .NET 4 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>
  • Перезапустите визуальную студию.

Теперь SqlEntityConnection компилируется во время разработки, и вы сможете увидеть все доступные таблицы. Это также с радостью скомпилируется в исполняемый файл.

Это отвечает на ваш вопрос; но теперь о странном моменте, который будет означать, что вы все еще недовольны. Когда вы запускаете этот код, он выдает ArgumentException, как только вызывается dbSchema.GetDataContext(), говоря:

Предоставляемая строка подключения должна быть либо допустимой строкой подключения, зависящей от поставщика, либо допустимой строкой подключения, принятой EntityClient.

Состояние внутреннего исключения

Ключевое слово server не поддерживается.

с трассировкой стека

в System.Data.EntityClient.EntityConnectionStringBuilder.set_Item (ключевое слово String, значение объекта) в System.Data.Common.DbConnectionStringBuilder.set_ConnectionString (значение String) в System.Data.EntityClient.EntityConnectionStringBuilder..ctor (String connectionString) .GetDataContext ()

Я пробовал испортить строку подключения, чтобы заставить ее работать, но я думаю, что это должно быть ошибкой в ​​том, как поставщик создает строку подключения во время выполнения и во время разработки. Поскольку этот код передается в динамическую сборку, неясно, как вы могли бы посмотреть на код, чтобы увидеть, что происходит.

person satnhak    schedule 10.08.2013
comment
Спасибо за ответ, я проверю и дам вам знать. - person kunjee; 10.08.2013

Встречаюсь с той же трудностью. Это исправлено добавлением этого в файл 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>

person user4119882    schedule 08.10.2014