简体   繁体   中英

EF 5.0 Fluent mapping: “EntityType '{ClassMap}' has no key defined. Define the key for this EntityType.”

Context:

I'm using EF5 as my connection between MODEL & Database. I have the following layers for my solution:

  • Company.Common (includes common classes & interfaces);
  • Company.Common.Data.Sql.EF (includes common class & interfaces in relation to EF);
  • Company.App.Model (includes the model of the application + IModelRepository classes, without reference to EF);
  • Company.App.Data.Sql.EF (includes the EF database implemntation based on the model of the application)
  • Company.App.Services (holds the services, which consumes the IModelRepositories etc...)

Problem description:

The error I get is the following: base {System.Exception} = {"One or more validation errors were detected during model generation:\\r\\n\\r\\n\\tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'AnnualPeriodMap' has no key defined. Define the key for this EntityType.\\r\\n\\tSystem.Data.Entity.Edm.EdmEntitySet: EntityTy...

My model classes are as basic as I can, but to help myself from typing redundant code, some of the model classes inherit from a class I called EntityBase , which simply holds the Id property. Below is the code for this class:

/// <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 itself inherits from IEntity , which is defined in Company.Common.Data, here's the code for this interface:

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

I did all of this to make my life easier when having to declare model entities that share same old data, such as Id's... Below is the code of a model class i'm experiencing issues with at the moment, namely AnnualPeriod , which as you can see inherits from EntityBase (of long) . EntityBase itself is shown above, the first code example...

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

My EF mapping is done via EntityTypeConfiguration (of ModelClass) classes, an example of such a mapping below:

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");
    }
}

Now when executing the code, I experience that EF5 says that EntityType 'AnnualPeriodMap' has no key defined. Define the key for this EntityType . I don't understand what I'm doing wrong, as I cleary stated the code this.HasKey(e => e.Id) in my AnnualPeriodMap (EntityTypeConfiguration) class.

It's obvious I'm doing something wrong, in either configuration, or in not understanding how EF works properly. But I haven't found any information about setting up constructions like this on the internet...

Thanks in advance for your advice, Yves Schelpe

It seems like there will be a way around this in EF6 with Custom Conventions. See [ http://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/DEV-B335#fbid=yJPWH45LEuw ] (at around 00:20:00 of the talk).

Please mention Key attribute

namespace:using using 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; }
 }

For me the solution was to add the EntityTypeConfiguration into the DbContext initialization. I had declared correctly the DbSet but for an unknown reason I totally forgot to configure it! Something like:

public IDbSet<AnnualPeriod> AnnualPeriods { get; set; }

void OnModelCreating(DbModelBuilder modelBuilder){
   ....
   //I was missing this line
   modelBuilder.Configurations.Add(new AnnualPeriodMap ());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM