我想将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; }
    }
    

    我做了什么:
  • 上面写了代码
  • 创建了DatabaseContext类
  • 在app.config中添加了DbProviderFactories和connectionStrings
  • 使用EdmGen.exe工具生成的ssdl,msl,csdl文件,并将它们复制到项目中(这些文件也位于bin文件夹中)

  • 数据库上下文:
    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();
    

    输出和错误:

    “yep” ..表示数据库存在。
    但是当访问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文件最适合?
  • 为什么Customer类不属于当前上下文模型的一部分?

  • 使用EdmGen.exe工具时,它还会生成一个ObjectLayer.cs文件,其中包含ObjectContext和实体类。问题在于,实体类是从EntityObject派生的。如果我想将实体类用作业务类,这是一个严重的问题,因为这些类不能从任何其他类派生。

    而且我不明白为什么它会生成一个ObjectContext ..我发现的每个HowTo都使用DbContext类。

    由EdmGen工具生成的Entity Customer类:
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    [EdmEntityTypeAttribute(NamespaceName="EF5", Name="Customer")]
    [Serializable()]
    [DataContractAttribute(IsReference=true)]
    public partial class Customer : EntityObject
    

    我很困惑 :-)

    编辑:
  • 我没有使用ObjectLayer.cs文件!由于上面提到的继承问题,我也不想使用它。部分客户类仅是显示EdmGen工具生成的示例。
  • 删除csdl,msl和ssdl文件时,出现以下错误:
    At least one SSDL artifact is required for creating StoreItemCollection.
    
  • 从app.config中的connectionString属性中删除metadata关键字时,出现以下错误:
    Some required information is missing from the connection string. The 'metadata' keyword is always required.
    



  • 解决方案:

    我终于弄清楚了它是如何工作的。 app.config中的connectionString错误。正确的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
    

    最佳答案

    您不应该生成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>
    

    关于.net - PostgreSQL的 Entity Framework 5.0,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12709718/

    10-13 04:38