The entity type 'Patient' requires a primary key to be defined means EF Core found no
property it could use as the key: nothing called Id or PatientId, no
[Key] attribute and no HasKey call. Mark the real key with [Key],
configure it with HasKey, or rename it to Id, and the model builds.
Reach for HasNoKey, the option the message suggests, only for data you never insert or
update through EF. Adding an instance of a keyless type threw
Unable to track an instance of type 'DailyCount' because it does not have a primary key.
The error
Unhandled exception. System.InvalidOperationException: The entity type 'Patient' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateNonNullPrimaryKeys(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
at Microsoft.EntityFrameworkCore.Sqlite.Infrastructure.Internal.SqliteModelValidator.Validate(IModel model, IDiagnosticsLogger`1 logger)
Why it happens
The first time a context is used, here by EnsureCreated(), EF Core builds the model from
your classes and validates it; the stack trace runs from ModelSource.CreateModel into
ModelValidator. Every entity type EF tracks needs a primary key, and the validator stops at
the first one without. The entity looked like this:
public class Patient
{
public string PatientNumber { get; set; } = "";
public string FullName { get; set; } = "";
}
PatientNumber is a sensible key, but EF does not guess from meaning; it looks for names.
To see exactly which names it accepts, the same check ran against thirteen small classes with EF Core
10.0.12, reading the key EF chose from the model:
- Found:
Id,IDandid;DoctorIdon classDoctor;NurseIDon classNurse;Idwith a private setter; astring Id; aGuid ShiftIdon classShift. - Not found, same error:
Ward_IdonWard;PatientIdon a class namedPatientRecord, because the prefix must be the class name;ClinicNumber; a public fieldId; a get-only propertyId { get; }.
The fix
public class Patient
{
[Key]
public string PatientNumber { get; set; } = "";
public string FullName { get; set; } = "";
}
With using System.ComponentModel.DataAnnotations; at the top of the file, the program
created the database, saved the patient and printed Patients in the database: 1. The
fluent version, with no attribute on the class, worked the same way:
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.Entity<Patient>().HasKey(p => p.PatientNumber);
Use the attribute when you are happy to keep mapping details on the entity, and HasKey when
you keep entity classes free of EF concerns. Renaming the property to Id also satisfies the
convention, but only do it if a column called Id is what you actually want.
How it was reproduced
A console app from dotnet new console with Microsoft.EntityFrameworkCore.Sqlite 10.0.12, a
ClinicDb context on a local SQLite file, one Patient entity keyed by
PatientNumber with no configuration, and db.Database.EnsureCreated() as the
first call. The naming check built one context per class so that one failure could not hide another.
.NET SDK 10.0.401, runtime 10.0.12, Windows 11.
Frequently asked
- How do I fix The entity type requires a primary key to be defined?
- Tell EF Core which property is the key: put [Key] on it, call modelBuilder.Entity<T>().HasKey(x => x.YourKey) in OnModelCreating, or name the property Id or the class name followed by Id so the convention finds it.
- Does EF Core recognise Id in any letter case?
- In a test with EF Core 10.0.12, Id, ID and id were all found, and so were DoctorId and NurseID on classes named Doctor and Nurse. Ward_Id, and PatientId on a class named PatientRecord, were not.
- When should I use HasNoKey in EF Core?
- Only for data you read but never insert, update or delete through EF. EF cannot track a keyless entity: adding one throws Unable to track an instance because it does not have a primary key.
More decoded errors in the Fixes category. Unsure whether a natural value like a patient number should be the key at all? See Primary Keys: Identity, GUID or Natural Key?