我想使用實體框架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="Server=asdf;Port=5432;User Id=asdf;Password=asdf;Database=asdf;enlist=true"" />
</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
它看起來像你試圖混合模型優先和代碼優先的工作流程。查看[http://msdn.com/data/ef](http://msdn.microsoft.com/en-us/data/ee712907)上的一些入門視頻,瞭解有關使用EF的更多信息。 – bricelam
一個簡單的例子會很棒。一個使用EF5和PostgreSql數據庫的項目。沒有任何設計者,只需編碼(歸屬代碼)。 – bakunin
完成:[PostgreSQL實體框架](http://brice-lambson.blogspot.com/2012/10/entity-framework-on-postgresql.html) – bricelam