2013-02-04 11 views
9

Próbuję uzyskać kod EF 5.0 po raz pierwszy współpracujący z PostgreSQL (dostawca Npgsql). Mam Npgsql 2.0.12.1 zainstalowany przez NuGet (referencyjny montaż to jednak 2.0.12.0). mam Npgsql zadeklarowane w app.config (zarówno fabryczne połączenie i fabryka dostawcy):Entity Framework 5.0 PostgreSQL (Npgsql) domyślna fabryka połączeń

<entityFramework> 
    <defaultConnectionFactory type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" /> 
</entityFramework> 
<system.data> 
     <DbProviderFactories> 
      <add name="Npgsql Data Provider" 
       invariant="Npgsql" 
       description="Data Provider for PostgreSQL" 
       support="FF" 
       type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7"/> 
     </DbProviderFactories> 
</system.data> 

Mam następujący test działa skutecznie:

[Test] 
public void DatabaseConnection_DatabaseFactoryTest() 
{ 
    var factory = DbProviderFactories.GetFactory("Npgsql"); 
    var conn = factory.CreateConnection(); 
    conn.ConnectionString = _connectionString; 
    var npg = (NpgsqlConnection)conn; 
    var result = TestConnectionHelper(npg); // scalar select version(), nothing particular 
    Assert.AreEqual(result, "PostgreSQL 9.2.2, compiled by Visual C++ build 1600, 64-bit");    
} 

Oznacza to, że co najmniej instancji bazy danych jest uruchomiony i dostawca jest skonfigurowany pomyślnie. Teraz to, co chcę jest użycie własnego kontekstu bazy danych odziedziczoną DbContext które będą przywiązane do tego samego dostawcy i zainicjowany przez ciąg połączenia:

public class InventoryContext : DbContext 
{ 
    public InventoryContext(string nameOrConnectionString) : base(nameOrConnectionString) 
    { 
    } 
    // mappings and properties, cut for conciseness 
} 

następstwie niepowodzenia testu:

[Test] 
public void DatabaseConnection_DatabaseContextTest() 
{ 
    using (var ctx = new InventoryContext(_connectionString)) 
    { 
     //var db = ctx.Database; 
     ctx.InventoryObjects.Add(_inventoryObject); // exception here 
     ctx.SaveChanges(); 
    } 
} 

Mówi

Failed to set Database.DefaultConnectionFactory to an instance of the 'Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7' type as specified in the application configuration. See inner exception for details. 

Wewnętrzny wyjątek to InvalidOperationException:

{"Constructor for type \"Npgsql.NpgsqlFactory\" is not found."} 

myślę, że jest problem z ciąg połączenia (nie zawiera dostawcę Npgsql):

"Server=127.0.0.1;Port=5432;User Id=postgres;Password=p4ssw0rd;Database=InventoryDatabase;"; 

Jaki jest najbardziej elegancki sposób, aby rozwiązać ten problem programowo? Właśnie próbowałeś przekazać connectionString z app.config do konstruktora kontekstu, to działa.
edit
Zamieszczone projekt testowy do Dropbox - VS2012 solution, 10 mb

+0

Witam! To ostatnie .1 w pakiecie nuget, ponieważ nie mogłem zaktualizować pakietu 2.0.12. W pakiecie był brakujący plik i musiałem go zaktualizować. Ale zapewnij, że plik binarny Npgsql jest taki sam jak wersja 2.0.12. :) Czy mógłbyś wysłać mi ten przykładowy projekt, abym mógł go obejrzeć? Myślę, że może to być błąd w Npgsql, którego może brakować konstruktor EF. Mój e-mail to francisco w npgsql dor org. Z góry dziękuję. –

+0

Wersja nie jest problemem, chociaż straciłem trochę czasu, aby dowiedzieć się, dlaczego nie znaleziono zestawu podczas pracy. Punkt jest naprawdę w konfiguracji ciągów połączeń, szczególnie w tym, że w moim środowisku produkcyjnym nie mogę używać/modyfikować plików .config (aplikacja WPF XBAP opublikowana w ograniczeniach IIS). Wyślę ci przykładowy projekt za kilka godzin. – Jaded

+0

Wysłano przykładowy projekt, dodano link do pobrania Dropbox, jeśli ktoś inny chce wyglądać. – Jaded

Odpowiedz

7

Dug głębiej w problem, okazało się, że jest to spowodowane tym iż Npgsql odwołuje EntityFramework 4.4.0 montaż. Rozwiązany w następujący sposób:

  1. Dodano pakiet EF Nuget do przetestowania projektu (który opiera się na FW 4.5);
  2. Ręcznie dodane odwołanie do EntityFramework.dll wersja 5 w projekcie Npgsql2010 (Nuget domyślnie dodaje 4.4.0);
  3. Zmienione zespół wiążący w Npgsql app.config do "EntityFramework, Version = 5.0.0.0 Kultura = neutralne TokenKluczaPublicznego = b77a5c561934e089";
  4. Poprawiono opisane powyżej „konstruktor typu«Npgsql.NpgsqlFactory»nie znajduje błąd poprzez konstruktor publiczny;
  5. Poprawiono następujący błąd «Nie obsada NpgsqlFactory do IDbConnectionFactory» wdrażając IDbConnectionFactory interfejs na NpgsqlFactory:

    przy użyciu System.Data.Entity.Infrastructure;
    ...
    publicznego uszczelnione klasa NpgsqlFactory: DbProviderFactory, IServiceProvider, IDbConnectionFactory
    ...
    publicznego DbConnection CreateConnection (nameOrConnectionString string)
    {
    powrót nowy NpgsqlConnection (nameOrConnectionString);
    }
    d

teraz jestem przeżywa "Błąd: 3F000: schema "dbo" nie istnieje", który jest związany z EF. Mam mapowanie do publicznego schematu PostgreSQL w DbContext's OnModelCreating: modelBuilder.Entity(). ToTable ("TableName", "public") jednak. Oczekuję rozwiązania tego problemu.

+0

Świetnie! Dodaję od razu zgłoszone brakujące elementy: widoczność konstruktora i implementację interfejsu. Dzięki za sprawdzenie. –

+1

Myślę, że skoczyłem za szybko. Podczas sprawdzania dokumentacji msdn zauważyłem, że SqlClientFactory to jedno, a SqlConnectionFactory to kolejna. NpgsqlFactory jest odpowiednikiem SqlClientFactory. Aby rozwiązać ten problem, musimy stworzyć kolejną klasę o nazwie NpgsqlConnectionFactory, która będzie powiązana z obsługą Entity Framework. Przepraszam za to. Sprawdzę, jak to zrobimy. –

+0

Poddałem się przy użyciu EntityFramework z PostgreSQL i Npgsql te problemy zostały naprawione. Nie ma mowy, że wchodzę do produkcji, dopóki nie będzie stabilniej. – Jammer

Powiązane problemy