【问题标题】:EF 5.0 Fluent mapping: "EntityType '{ClassMap}' has no key defined. Define the key for this EntityType."EF 5.0 Fluent 映射:“EntityType '{ClassMap}' 没有定义键。定义此 EntityType 的键。”
【发布时间】:2013-06-12 11:11:46
【问题描述】:

上下文:

我使用 EF5 作为模型和数据库之间的连接。 我的解决方案有以下几层:

  • Company.Common(包括通用类和接口);
  • Company.Common.Data.Sql.EF(包括与 EF 相关的通用类和接口);
  • Company.App.Model(包括应用程序的模型 + IModelRepository 类,不参考 EF);
  • Company.App.Data.Sql.EF(包括基于应用模型的EF数据库实现)
  • Company.App.Services(保存服务,使用 IModelRepositories 等...)

问题描述:

我得到的错误如下: base {System.Exception} = {"在模型生成过程中检测到一个或多个验证错误:\r\n\r\n\ tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'AnnualPeriodMap' 没有定义键。定义此 EntityType 的键。\r\n\tSystem.Data.Entity.Edm.EdmEntitySet: EntityTy...

我的模型类尽可能基本,但为了帮助自己避免输入冗余代码,一些模型类继承自我称为 EntityBase 的类,该类仅包含 Id 属性。下面是这个类的代码:

/// <summary>
/// Base implementation for IEntity.
/// </summary>
/// <typeparam name="TId">The type of the id.</typeparam>
public abstract class EntityBase<TId> : IEntity<TId>        
{
    public virtual TId Id { get; set; }        
    object IEntity.Id
    {
        get
        {
            return this.Id;
        }
        set
        {
            this.Id = (TId)value;
        }
    }
}

EntityBase本身继承自IEntity,在Company.Common.Data中定义,下面是这个接口的代码:

public interface IEntity
{
    /// <summary>
    /// The entity's id.
    /// </summary>
    object Id { get; set; }
}

/// <summary>
/// Defines an entity.
/// </summary>
/// <typeparam name="TKey">The type of the entity's key.</typeparam>
public interface IEntity<TKey> : IEntity
{
    /// <summary>
    /// The entity's id.
    /// </summary>
    new TKey Id { get; set; }
}

我所做的所有这些都是为了让我的生活更轻松,因为我必须声明共享相同旧数据的模型实体,例如 Id ......下面是我目前遇到问题的模型类的代码,即AnnualPeriod,如您所见,它继承自 EntityBase (of long)。 EntityBase本身如上图,第一个代码示例...

public class AnnualPeriod : EntityBase<long>
{
    public virtual int AnnualPeriodTypeId { get; set; }
    public virtual AnnualPeriodType AnnualPeriodType { get; set; }
    public virtual string Code { get; set; }
    public virtual DateTime StartDate { get; set; }
    public virtual DateTime EndDate { get; set; }

    public virtual ICollection<Counter> Counters { get; set; }
}

我的 EF 映射是通过 EntityTypeConfiguration (of ModelClass) 类完成的,下面是此类映射的一个示例:

public class AnnualPeriodMap : EntityTypeConfiguration<AnnualPeriod>
{
    public AnnualPeriodMap()
    {
        // Table
        this.ToTable("AnnualPeriods");

        // Primary Key
        this.HasKey(e => e.Id);

        // Columns
        this.Property(e => e.Id).HasColumnName("id");
        this.Property(e => e.AnnualPeriodTypeId).HasColumnName("annualPeriodTypeId");
        this.Property(e => e.Code).HasColumnName("code");
        this.Property(e => e.StartDate).HasColumnName("startDate");
        this.Property(e => e.EndDate).HasColumnName("endDate");
    }
}

现在在执行代码时,我发现 EF5 说 EntityType 'AnnualPeriodMap' 没有定义键。定义此 EntityType 的键。我不明白我做错了什么,因为我清楚地在我的 AnnualPeriodMap (EntityTypeConfiguration) 类中声明了代码 this.HasKey(e => e.Id) .

很明显我做错了,无论是在配置中,还是在不了解 EF 如何正常工作方面。但是我在网上没有找到任何关于设置这样的结构的信息......

提前感谢您的建议, 伊夫·谢尔佩

【问题讨论】:

    标签: c# entity-framework-5 fluent


    【解决方案1】:

    在 EF6 中似乎有一种方法可以通过自定义约定来解决这个问题。 请参阅 [http://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/DEV-B335#fbid=yJPWH45LEuw](演讲时间大约 00:20:00)。

    【讨论】:

      【解决方案2】:

      请提及关键属性

      命名空间:使用 System.ComponentModel.DataAnnotations;

       public class AnnualPeriod : EntityBase<long>
       {
      [Key]
      public virtual int AnnualPeriodTypeId { get; set; }
      public virtual AnnualPeriodType AnnualPeriodType { get; set; }
      public virtual string Code { get; set; }
      public virtual DateTime StartDate { get; set; }
      public virtual DateTime EndDate { get; set; }
      
      public virtual ICollection<Counter> Counters { get; set; }
       }
      

      【讨论】:

      • 感谢您的回复!正如您在我最初的解释中看到的那样,我有几个层,这是为了确保我可以在不同的上下文中重用我的模型。我的意思是,我希望它与任何库(如 nHibernate、EF 等)分离。这就是为什么我在另一个项目/层中进行映射,而这我不想在我的模型项目中使用注释/层,这会破坏分离。我想补充一点,“public virtual int AnnualPeriodTypeId”是一个外键,真正的主键在 EntityBase 中定义,以防万一这在我最初的帖子中并不明显..
      • 如果 AnnualPeriodTypeId 是外键,那么 [ForeignKey("AnnualPeriodTypeId")] public string AnnualPeriodTypeId { get;放; }
      • 请阅读上面的评论,我想使用 EntityTypeConfiguration 类映射样式的流利配置,而不是通过数据注释,因为它弄乱了我的模型层......
      【解决方案3】:

      对我来说,解决方案是将 EntityTypeConfiguration 添加到 DbContext 初始化中。我已经正确声明了 DbSet,但由于未知原因,我完全忘记了配置它!比如:

      public IDbSet<AnnualPeriod> AnnualPeriods { get; set; }
      
      void OnModelCreating(DbModelBuilder modelBuilder){
         ....
         //I was missing this line
         modelBuilder.Configurations.Add(new AnnualPeriodMap ());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-02
        • 2016-03-16
        • 2013-08-04
        • 2012-12-10
        • 2016-09-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多