The entity type 'Access' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'

29,077

Solution 1

EF Core has the concept of Owned Entity Types, which can be used to implement DDD value types.

In OnModelCreating you would do the following:

modelBuilder.Entity<AccessLevel>().OwnsOne(x => x.Access);

This would store Access objects in the same database table as AccessLevel objects, and therefore requires no primary key.

Solution 2

If you are scaffolding a .net controller using a model and you get this error

The entity type 'Access' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'

is because the model you are using in your command does not have and key property

By convention, a property named Id or Id will be configured as the primary key of an entity.

internal class Car
{
    public string Id { get; set; } //this is the key

    public string Make { get; set; }
    public string Model { get; set; }
}

internal class Truck
{
    public string TruckId { get; set; } //this is the key

    public string Make { get; set; }
    public string Model { get; set; }
}

When you primary key does not follow that convention you can use the [Key] to indicate what propierty is you entity key

public class GameStats {
    [Key]
    public String playerName {set; get;}
    public int gamesWon {set; get;}
}

If your entinty does not have keys you can use [KeyLess]

[Keyless]
public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

Taken from

Share:
29,077
kia kia
Author by

kia kia

Updated on July 05, 2022

Comments

  • kia kia
    kia kia almost 2 years

    i have this ValueObject :

    public class Access : ValueObject<Access>
    {
        public string ControllName { get;  set; }
        public string ActionName { get;  set; }
    
        private Access()
        {
    
        }
        public Access(string controllerName, string actionName)
        {
            ControllName = controllerName;
            ActionName = actionName;
        }
    
        protected override IEnumerable<object> GetEqualityComponents()
        {
            yield return ControllName;
            yield return ActionName;
        }
    }
    

    and this is my ValueObject<Access> :

     public abstract class ValueObject<T>
        where T : ValueObject<T>
    {
        protected abstract IEnumerable<object> GetEqualityComponents();
    
        public override bool Equals(object obj)
        {
            var valueObject = obj as T;
    
            if (ReferenceEquals(valueObject, null))
                return false;
    
            return IsEquals(valueObject);
        }
    
        private bool IsEquals(ValueObject<T> other)
        {
            return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
        }
    
        public override int GetHashCode()
        {
            return GetEqualityComponents()
                .Aggregate(1, (current, obj) => current * 23 + (obj?.GetHashCode() ?? 0));
        }
    
        public static bool operator ==(ValueObject<T> a, ValueObject<T> b)
        {
            if (ReferenceEquals(a, null) && ReferenceEquals(b, null))
                return true;
    
            if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
                return false;
    
            return a.Equals(b);
        }
    
        public static bool operator !=(ValueObject<T> a, ValueObject<T> b)
        {
            return !(a == b);
        }
    }
    

    and this is my DBContext :

     public class StoreAdminPanelGetwayContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder.UseSqlServer(@"Server=.; initial catalog=StoreAdminPanelGetway;integrated security=true");
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ApplyConfigurationsFromAssembly(typeof(Role).Assembly);
        }
        public DbSet<Role> Roles { get; set; }
        public DbSet<AccessLevel> AccessLevels { get; set; }
    
    }
    

    this is my entity :

      public class AccessLevel : Entity
    {
        public int RoleId { get;  set; }
        public Access Access { get;  set; }
        public Role Role { get; set; }
    }
    

    but when i need to add-migration initial databse it show me this error :

    The entity type 'Access' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'.

    but Access is value object and it can not have an id . how can i solve this problem ???

  • Fabooo
    Fabooo over 3 years
    You could also do this for single values builder.Property(c => c.Access) .HasConversion(c => c.Value, c => new Access(c.action, c.controller));
  • Dilnoor Singh
    Dilnoor Singh about 3 years
    Just a note: This is applicable starting from EF Core 5.0 and above.