My problem is I get this error
The entity type 'List' 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."
I searched about it and did everything.
id
is public, and the data annotation [Key]
is there. I don't know what else to do.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Business_Layer
{
public class ExerciseType
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public BodyParts TargetetMuscle { get; set; }
public Equipment Equipment { get; set; }
public List<Exercise> Exercises { get; set; }
public ExerciseType()
{
Exercises = new List<Exercise>();
}
public ExerciseType(string name, string description, BodyParts targetedmuscle, Equipment equipment)
{
Exercises = new List<Exercise>();
Name = name;
Description = description;
TargetetMuscle = targetedmuscle;
Equipment = equipment;
}
}
}
namespace Business_Layer
{
public class Exercise
{
[Key]
public int Id { get; set; }
[Required]
public int Weight { get; set; }
[Required]
public int Reps { get; set; }
[Required]
public Status status { get; set; }
public ExerciseType exerciseType { get; set; }
public List<Workout> workouts { get; set; }
public Exercise()
{
workouts = new List<Workout>();
}
public Exercise(string name, string description,int weight, int reps)
{
status = Status.Waiting;
Weight = weight;
Reps = reps;
workouts = new List<Workout>();
}
}
}
namespace Business_Layer
{
public class User
{
[Key]
public string Id { get; set; }
[Required]
[MaxLength(50, ErrorMessage = "Name cannot be more than 50 symbols!")]
public string Name { get; set; }
public List<Workout> Workouts { get; set; }
public List<Workout> History { get; set; }
public User()
{
History = new List<Workout>();
Workouts = new List<Workout>();
}
public User(string name)
{
Id = Guid.NewGuid().ToString();
Name = name;
History = new List<Workout>();
Workouts = new List<Workout>();
}
}
}
namespace Business_Layer
{
public class Workout
{
[Key]
public int WorkoutId { get; set; }
public List<Exercise> Exercises { get; set; }
public User Creator { get; set; }
public List<User> Users { get; set; }
public Status Status { get; set; }
public Workout()
{
Exercises = new List<Exercise>();
}
public Workout(User user)
{
Status = Status.Waiting;
Users = new List<User>();
Exercises = new List<Exercise>();
}
}
}
public class TrackerDBContext:DbContext
{
public TrackerDBContext()
{
}
public TrackerDBContext(DbContextOptions contextOptions) : base(contextOptions)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=DESKTOP-PTKBD3O\\SQLEXPRESS01;Database=FitnessTrackerDB;Trusted_Connection=True;");
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ExerciseType>()
.Property(a => a.TargetetMuscle)
.HasConversion<string>();
modelBuilder.Entity<ExerciseType>()
.Property(o => o.Equipment)
.HasConversion<string>();
modelBuilder.Entity<User>()
.HasMany(e => e.Workouts)
.WithMany(e=>e.Users);//napravi vruzka mejdu history i workouts
modelBuilder.Entity<User>()
.HasOne(e => e.History);
modelBuilder.Entity<Workout>()
.HasOne(e => e.Creator);
base.OnModelCreating(modelBuilder);
}
public DbSet<User> Users { get; set; }
public DbSet<Workout> Workouts { get; set; }
public DbSet<Exercise> Exercises { get; set; }
public DbSet<ExerciseType> ExerciseTypes { get; set; }
}
This line is the culprit:
modelBuilder.Entity<User>()
.HasOne(e => e.History);
Since e.History
is a List<T>
, but mapped as a reference (HasOne
), EF interprets the type as a mapped type. Then it looks for a property that qualifies as a primary key according to EF's name conventions, and finds none.
Obviously, the mapping should be:
modelBuilder.Entity<User>()
.HasMany(e => e.History);
Adhering to common naming conventions (use plural names for collection properties) might have helped prevent this error.