2012-10-03 10 views
8

Chciałbym użyć Entity-Framework 5.0 jako programu odwzorowującego O/R z bazą danych PostgreSql. Czytałem już wiele porad, ale nadal utknąłem. Może nie rozumiem całej idei EF.Entity-Framework 5.0 z PostgreSQL

Czego chcę:

  • Chcę napisać kod przez własną rękę. Następnie umieść kilka atrybutów we właściwościach i klasach, aby powiedzieć EF, jak odwzorować obiekty (tak jak zrobiłbym to przy pomocy NHibernate).
  • Nie chcę generować bazy danych z mojego modelu - chcę tylko użyć istniejącej.

Przykład Model:

[Table("device")] 
public class Device 
{ 
    [Key] 
    public int Id { get; set; } 

    [StringLength(255)] 
    public string Identifier { get; set; } 
} 

[Table("customer")] 
public class Customer 
{ 
    public Customer() 
    { 
     this.Devices = new List<Device>(); 
    } 

    [Key] 
    public int Id { get; set; } 

    [StringLength(255)] 
    public string Name { get; set; } 

    // attribute required? 
    public List<Device> Devices { get; set; } 
} 

Co zrobiłem:

  • Napisanie kodu powyżej
  • Utworzono klasę DatabaseContext
  • Dodany DbProviderFactories i connectionStrings w th e app.config
  • Generated SSDL, MSL, CSDL plików za pomocą narzędzia EdmGen.exe i kopiowane je w projekcie (te pliki w folderze bin są również)

DatabaseContext:

public class DatabaseContext : DbContext 
{ 
    static DatabaseContext() 
    { 
     Database.SetInitializer<DatabaseContext>(null); 
    } 

    public DatabaseContext() 
     : base("PostgreSQL") 
    { 

    } 

    public DbSet<Customer> Customers { get; set; } 
    public DbSet<Device> Devices { get; set; } 
} 

app.config:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <configSections> 
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> 
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> 
    </configSections> 
    <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 
    </startup> 

    <system.data> 
    <DbProviderFactories> 
     <remove invariant="Npgsql" /> 
     <add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql Server" type="Npgsql.NpgsqlFactory, Npgsql, Version=2.0.12.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" /> 
    </DbProviderFactories> 
    </system.data> 

    <connectionStrings> 
    <add name="PostGreSQL" 
     providerName="System.Data.EntityClient" 
     connectionString="metadata=.;provider=Npgsql;provider connection string=&quot;Server=asdf;Port=5432;User Id=asdf;Password=asdf;Database=asdf;enlist=true&quot;" /> 
    </connectionStrings> 

</configuration> 

Test:

using (DatabaseContext context = new DatabaseContext()) 
{ 
    if (context.Database.Exists()) 
    { 
     Console.WriteLine("yep"); 
    } 
    else 
    { 
     Console.WriteLine("nope"); 
    } 

    foreach (Customer c in context.Customers) 
    { 
     Console.WriteLine("Name={0}", c.Name); 
    } 
} 

Console.ReadLine(); 

Wyjście & Błąd:

"yep" .. co oznacza bazy istnieją. Ale gdy dostęp do właściwości context.Customers pojawia się następujący wyjątek:

The entity type Customer is not part of the model for the current context. 

StackTrace:

at System.Data.Entity.Internal.InternalContext.UpdateEntitySetMappingsForType(Type entityType) 
    at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) 
    at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() 
    at System.Data.Entity.Internal.Linq.InternalSet`1.GetEnumerator() 
    at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.Generic.IEnumerable<TResult>.GetEnumerator() 
    at EF5.Program.Main(String[] args) in c:\Users\tba\Documents\Visual Studio 2012\Projects\EF5\EF5\Program.cs:line 26 
    at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
    at System.Threading.ThreadHelper.ThreadStart() 

Co ja nie rozumiem:

  • Jakie są ssdl, msl, csdl pliki dobre dla, jeśli DataAnnoations są dostępne?
  • Dlaczego klasa Klient nie jest częścią modelu dla bieżącego kontekstu?

Podczas korzystania z narzędzia EdmGen.exe generuje on również plik ObjectLayer.cs, który zawiera klasy ObjectContext i entity.Problem polega na tym, że klasy encji pochodzą z EntityObject. Jeśli chcę używać klas jednostek jako klas biznesowych, jest to poważny problem, ponieważ klasy nie mogą pochodzić z żadnych innych klas.

Ponadto nie rozumiem, dlaczego generuje ObjectContext. Każde znalezione HowTo używa klasy DbContext.

Podmiot klasa klienta wygenerowany przez narzędzie EdmGen:

/// <summary> 
/// No Metadata Documentation available. 
/// </summary> 
[EdmEntityTypeAttribute(NamespaceName="EF5", Name="Customer")] 
[Serializable()] 
[DataContractAttribute(IsReference=true)] 
public partial class Customer : EntityObject 

Jestem mylić :-)

Edit:

  • Nie używam tych ObjectLayer.cs plik! I nie chcę tego również używać ze względu na problemy z dziedziczeniem, o których pisałem powyżej. Częściowa klasa klienta jest tylko przykładem do pokazania, co generuje narzędzie EdmGen.
  • Kiedy usunąć CSDL, MSL i plików SSDL pojawia się następujący błąd:

    At least one SSDL artifact is required for creating StoreItemCollection. 
    
  • Kiedy usunąć słowa kluczowego metadanych z właściwości ConnectionString w app.config pojawia się następujący błąd:

    Some required information is missing from the connection string. The 'metadata' keyword is always required. 
    



Rozwiązanie:

W końcu zorientowałem się, jak to działa. Metoda connectionString w pliku app.config jest niepoprawna. Prawidłowe połączenie: Ciąg znaków:

Usunąłem metadane, dostawcę i właściwość łańcucha połączenia dostawcy z connectionString. Podobnie jak w przypadku Brice, pliki metadanych nie są konieczne, dlatego właśnie je usunąłem.

Również atrybut tabeli dla urządzenia i klasy klienta musi określać schemat . W ten sposób:

[Table("customer", Schema="public")] 
public class Customer 
+1

Wygląda na to, że próbujesz wymieszać przepływy pracy od pierwszego modelu do pierwszego kodu. Sprawdź niektóre z filmów Getting Started na stronie [http://msdn.com/data/ef](http://msdn.microsoft.com/en-us/data/ee712907), aby dowiedzieć się więcej o korzystaniu z EF. – bricelam

+1

Prosty przykład byłby świetny. Projekt korzystający z EF5 z bazą danych PostgreSql. Bez żadnego projektanta, po prostu kod (przypisany kod). – bakunin

+2

Zrobione: [Entity Framework na PostgreSQL] (http://brice-lambson.blogspot.com/2012/10/entity-framework-on-postgresql.html) – bricelam

Odpowiedz

4

Nie powinieneś generować plików ssdl, msl, csdl. Te pliki są wymagane tylko, jeśli chcesz używać projektanta. Usuń te pliki i wygenerowany obiekt ObjectLayer.cs.

Nie należy również używać ciągu połączenia EntityClient. Zaktualizuj ciąg połączenia tak, aby był następujący.

<connectionStrings> 
    <add name="PostGreSQL" 
     providerName="Npgsql" 
     connectionString="Server=asdf;Port=5432;User Id=asdf;Password=asdf;Database=asdf;enlist=true" /> 
</connectionStrings> 
+0

Zobacz mój zredagowany post.Nie używam pliku ObjectLayer.cs. – bakunin

+0

Zaktualizowałem moją odpowiedź. Wygląda na to, że twoim problemem jest po prostu ciąg połączenia. – bricelam

+0

Doh, wygląda na to, że działa. :) Dobra robota – bricelam

Powiązane problemy