The entity type 'Access' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'
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
- https://docs.microsoft.com/en-us/ef/core/modeling/keys?tabs=data-annotations
- https://docs.microsoft.com/en-us/ef/core/modeling/keyless-entity-types?tabs=data-annotations
kia kia
Updated on July 05, 2022Comments
-
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 over 3 yearsYou 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 about 3 yearsJust a note: This is applicable starting from EF Core 5.0 and above.