【问题标题】:The entity type 'Access' requires a primary key to be defined. If you intended to use a keyless entity type call 'HasNoKey()'实体类型“访问”需要定义一个主键。如果您打算使用无密钥实体类型调用“HasNoKey()”
【发布时间】:2020-03-09 12:44:13
【问题描述】:

我有这个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;
    }
}

这是我的ValueObject&lt;Access&gt;

 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);
    }
}

这是我的 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; }

}

这是我的实体:

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

但是当我需要add-migration initial 数据库时,它会显示这个错误:

实体类型“Access”需要定义一个主键。如果您打算使用无密钥实体类型调用“HasNoKey()”。

Access 是值对象,它不能有 id 。我该如何解决这个问题???

【问题讨论】:

    标签: c# asp.net entity-framework entity-framework-core domain-driven-design


    【解决方案1】:

    EF Core有Owned Entity Types的概念,可以用来实现DDD值类型。

    OnModelCreating 中,您将执行以下操作:

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

    这会将Access 对象与AccessLevel 对象存储在同一个数据库表中,因此不需要主键。

    【讨论】:

    • 您也可以对单个值执行此操作builder.Property(c =&gt; c.Access) .HasConversion(c =&gt; c.Value, c =&gt; new Access(c.action, c.controller));
    【解决方案2】:

    如果您正在使用模型构建 .net 控制器并收到此错误

    实体类型“Access”需要定义一个主键。如果你 打算使用无键实体类型调用“HasNoKey()”

    是因为你在命令中使用的模型没有 and key 属性

    按照约定,将配置一个名为 Id 或 Id 的属性 作为实体的主键。

    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; }
    }
    

    当您的主键不遵循该约定时,您可以使用[Key] 来指示您的实体键是什么属性

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

    如果您的实体没有密钥,您可以使用 [KeyLess]

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

    取自

    【讨论】:

    • 请注意:这适用于从 EF Core 5.0 及更高版本开始。
    【解决方案3】:

    如果您想将值对象保存在不同的表中,您可以使用影子属性来定义一个 ID,该 ID 将存在于数据库中,但不存在于您的模型中。

        builder.Entity< Access >( a =>
        {
            a.Property< int >( "Id" );
            a.HasKey( "Id" );
        } );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 2022-07-19
      • 2021-07-23
      • 2021-11-27
      • 2018-08-13
      相关资源
      最近更新 更多