带有PostgreSQL的Entity-Framework 5.0

bak*_*nin 8 .net postgresql entity-framework

我想使用Entity-Framework 5.0作为带有PostgreSql数据库的O/R映射器.我已经阅读了许多HowTos,但我仍然被卡住了.也许我没有得到EF背后的全部想法.

我想要的是:

  • 我想自己编写代码.然后将一些属性放到属性和类中,告诉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; }
}
Run Code Online (Sandbox Code Playgroud)

我做了什么:

  • 写了上面的代码
  • 创建了一个DatabaseContext类
  • 在app.config中添加了DbProviderFactories和connectionStrings
  • 使用EdmGen.exe工具生成ssdl,msl,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; }
}
Run Code Online (Sandbox Code Playgroud)

的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>
Run Code Online (Sandbox Code Playgroud)

测试:

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();
Run Code Online (Sandbox Code Playgroud)

输出和错误:

"是的"..这意味着数据库存在.但是当访问context.Customers属性时,我得到以下异常:

The entity type Customer is not part of the model for the current context.
Run Code Online (Sandbox Code Playgroud)

堆栈跟踪:

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()
Run Code Online (Sandbox Code Playgroud)

我不明白的是:

  • 如果DataAnnoations可用,那么ssdl,msl,csdl文件有什么用呢?
  • 为什么Customer类不属于当前上下文的模型?

使用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
Run Code Online (Sandbox Code Playgroud)

我很迷惑 :-)

编辑:

  • 我没有使用ObjectLayer.cs文件!由于我上面提到的继承问题,我也不想使用它.部分Customer类只是一个示例,用于显示EdmGen工具生成的内容.
  • 当我删除csdl,msl和ssdl文件时,我收到以下错误:

    At least one SSDL artifact is required for creating StoreItemCollection.
    
    Run Code Online (Sandbox Code Playgroud)
  • 当我从app.config中的connectionString属性中删除metadata关键字时,我收到以下错误:

    Some required information is missing from the connection string. The 'metadata' keyword is always required.
    
    Run Code Online (Sandbox Code Playgroud)



解:

我终于弄清楚它是如何工作的.app.config中的connectionString是错误的.正确的connectionString:

<connectionStrings>
    <add name="PostgreSQL"
        connectionString="Server=asdf;Port=5432;User Id=asdf;Password=asdf;Database=asdf;"
         providerName="Npgsql" />
</connectionStrings>
Run Code Online (Sandbox Code Playgroud)

我从connectionString中删除了元数据,提供程序和提供程序连接字符串属性.像Brice说的那样,元数据文件不是必需的,所以我只是将它们删除了.

此外,Device和Customer类的Table-Attribute需要指定架构.像这样:

[Table("customer", Schema="public")]
public class Customer
Run Code Online (Sandbox Code Playgroud)

bri*_*lam 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>
Run Code Online (Sandbox Code Playgroud)