8

Using EF 5 (reverse engineered code first), my model was working fine until it suddenly stopped.

\tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'ProjectsDate' has no key defined. Define the key for this EntityType.

\tSystem.Data.Entity.Edm.EdmEntityType: : EntityType 'ProjectsRisk' has no key defined. Define the key for this EntityType.

I define a key using fluent API rather than attributes, here is my ProjectsDates classes.

public partial class ProjectsDate
{
    public string OSProjectCode { get; set; }
    public Nullable<System.DateTime> TargetStart { get; set; }
    public Nullable<System.DateTime> EndDateOriginal { get; set; }
    public Nullable<System.DateTime> EndDateChangeControl { get; set; }
    public Nullable<System.DateTime> EndDateActual { get; set; }
    public Nullable<System.DateTime> GoLiveAgreed { get; set; }
    public Nullable<System.DateTime> GoLiveActual { get; set; }
    public virtual Project Project { get; set; }
}
public class ProjectsDateMap : EntityTypeConfiguration<ProjectsDate>
{
    public ProjectsDateMap()
    {
        // Primary Key
        this.HasKey(t => t.OSProjectCode);

        // Properties
        this.Property(t => t.OSProjectCode)
            .IsRequired()
            .HasMaxLength(10);

        // Table & Column Mappings
        this.ToTable("ProjectsDates");
        this.Property(t => t.OSProjectCode).HasColumnName("OSProjectCode");
        this.Property(t => t.TargetStart).HasColumnName("TargetStart");
        this.Property(t => t.EndDateOriginal).HasColumnName("EndDateOriginal");
        this.Property(t => t.EndDateChangeControl).HasColumnName("EndDateChangeControl");
        this.Property(t => t.EndDateActual).HasColumnName("EndDateActual");
        this.Property(t => t.GoLiveAgreed).HasColumnName("GoLiveAgreed");
        this.Property(t => t.GoLiveActual).HasColumnName("GoLiveActual");

        // Relationships
        this.HasRequired(t => t.Project)
            .WithOptional(t => t.ProjectsDate);

    }
}

Why doesn't EF see my fluent API mapping?

Slauma
  • 175,098
  • 59
  • 401
  • 420
Malkin
  • 159
  • 2
  • 13
  • 4
    Maybe you didn't add an instance of `ProjectsDateMap` to `modelBuilder.Configurations` in `OnModelCreating`? – Slauma May 09 '13 at 12:43
  • Just double checked, it is in OnModelCreating, cheers anyway – Malkin May 09 '13 at 12:47
  • What a pity, it had been such a simple explanation and fix :) Did you check in the debugger if the `HasKey` line is actually passed? – Slauma May 09 '13 at 12:50
  • Aye, I was ready to be embarrassed but happy it was working aha ;p. If I breakpoint the modelmap class should it be hit? I can't seem to hit the `OnModelCreating` or `HasKey` – Malkin May 09 '13 at 12:56
  • Yes, it should hit the line when you use a context for the first time after application start. Is this a project converted from db-first or model-first? Is it possible that you have an edmx somewhere still in the project or a connection string that contains metadata sections? EF would not see it as Code-First then and never call `OnModelCreating`. – Slauma May 09 '13 at 13:00
  • Hmm, I used EF Power Tools to reverse engineer from a database. – Malkin May 09 '13 at 13:07
  • Also, to throw a curve ball in, I recreated another context I also have, and this has made this context work and hit the breakpoints. Would this mean EF failed silently loading the first context and didn't bother getting to the second? – Malkin May 09 '13 at 13:08
  • 1
    Hm, don't understand exactly. Do you mean that in a second `using (var ctx = new MyContext())` `OnModelCreating` is called but not on the first one? You can btw edit your question to put new infos in there (use "edit" link below your question). It's a better place then a long comment thread. (I've changed your question title btw. "Entity Framework" wasn't that good as a meaningful title :)) – Slauma May 09 '13 at 13:12

3 Answers3

2

For some reason (probably a bug), FluentAPI needs the key to be defined in a convention way - that is - ClassName + Id, or in your case:

ProjectsDateId

This way the metadata created by EF can acknowledge the fact it is related. Very annoying but...

Tomer
  • 4,382
  • 5
  • 38
  • 48
  • Does not work. I have an entity named Offer, and I set the key to be named OfferID, but EF still complains no key is defined. The only thing that works is using [Key,ForeignKey("Offer")] on the property, and then the property can be named anything I want. – Triynko Feb 27 '18 at 16:14
1

You need to have a global binding or individual binding in OnModelCreating
(DbModelBuilder modelBuilder).

So it would look something like this in your context file:

public override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // global
    modelBuilder.Configurations.AddFromAssembly(GetType().Assembly);
    // individual
    modelBuilder.Configurations.Add(new ProjectsDateMap());
}
zx485
  • 28,498
  • 28
  • 50
  • 59
leeeennyy
  • 15
  • 4
0

I fixed this by re-running the reverse engineer code first from EF power tools. Seemed to work from there out, this seems to be a general problem that kicks up when your models aren't configured right. It's a shame it seems so general and just kicks up misleading errors.

Malkin
  • 159
  • 2
  • 13