2012-10-03 167 views
8

我想使用實體框架5.0作爲與PostgreSQL數據庫的O/R映射器。我已經閱讀了很多HowTos,但我仍然陷入困境。也許我不明白EF背後的想法。實體 - 框架5.0的PostgreSQL

我想要什麼:

  • 我希望由我自己寫的代碼。然後將一些屬性添加到屬性和類中,告訴EF如何映射對象(就像我會用NHibernate那樣)。
  • 我不想從我的模型生成數據庫 - 我只想使用現有的數據庫。

實例型號:

[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; } 
} 

我所做的:

  • 寫上面
  • 代碼創建一個DatabaseContext類
  • 新增DbProviderFactories和的ConnectionStrings在日Ë的app.config
  • 生成SSDL,MSL,與EdmGen.exe工具CSDL文件,並在項目中複製它們(這些文件也可以在bin文件夾中可用)

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> 

測試:

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(); 

輸出&錯誤:

「是的」 ..,這意味着存在於數據庫中。 但訪問context.Customers財產,我得到以下異常時:

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

堆棧跟蹤:

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

我不明白:

  • 是什麼如果DataAnnoations可用,ssdl,msl,csdl文件適用於?
  • 爲什麼客戶類不是當前上下文的模型的一部分?

當使用EdmGen.exe工具時,它還生成一個ObjectLayer.cs文件,其中包含一個ObjectContext和實體類。問題在於,實體類從EntityObject派生。如果我想使用實體類作爲商業類,這是一個嚴重的問題,因爲類不能從任何其他類派生。

此外,我不明白爲什麼它會生成一個ObjectContext ..每一個我發現的HowTo使用DbContext類。

由EdmGen工具生成實體Customer類:

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

我很困惑:-)

編輯:

    我沒有使用ObjectLayer.cs
  • 文件!由於我上面提到的繼承問題,我也不想使用它。部分Customer類只是一個示例,用於顯示EdmGen工具生成的內容。
  • 當我刪除了CSDL,MSL和SSDL文件,我得到以下錯誤:

    At least one SSDL artifact is required for creating StoreItemCollection. 
    
  • 當我在App.config我得到以下錯誤ConnectionString屬性刪除元數據關鍵字:

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



解決方案:

我終於弄清楚它是如何工作的。 app.config中的connectionString是錯誤的。正確的連接字符串:

<connectionStrings> 
    <add name="PostgreSQL" 
     connectionString="Server=asdf;Port=5432;User Id=asdf;Password=asdf;Database=asdf;" 
     providerName="Npgsql" /> 
</connectionStrings> 

我從connectionString中刪除了元數據,提供程序和提供程序連接字符串屬性。就像Brice說的那樣,元數據文件不是必需的,所以我只是刪除了它們。

此外,設備和客戶類的表屬性需要指定模式。像這樣:

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

它看起來像你試圖混合模型優先和代碼優先的工作流程。查看[http://msdn.com/data/ef](http://msdn.microsoft.com/en-us/data/ee712907)上的一些入門視頻,瞭解有關使用EF的更多信息。 – bricelam

+1

一個簡單的例子會很棒。一個使用EF5和PostgreSql數據庫的項目。沒有任何設計者,只需編碼(歸屬代碼)。 – bakunin

+2

完成:[PostgreSQL實體框架](http://brice-lambson.blogspot.com/2012/10/entity-framework-on-postgresql.html) – bricelam

回答

4

您不應該生成ssdl,msl,csdl文件。如果您想使用設計器,則只需要這些文件。刪除這些文件和生成的ObjectLayer.cs。

你也不應該使用EntityClient連接字符串。更新您的連接字符串,只需如下所示。

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

查看我編輯的帖子。我不使用ObjectLayer.cs文件。 – bakunin

+0

更新了我的答案。看起來你的問題只是連接字符串。 – bricelam

+0

Doh,看起來像你的工作。 :) 做得好 – bricelam