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

kia*_*kia 4 c# asp.net domain-driven-design entity-framework entity-framework-core

我有这个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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

}
Run Code Online (Sandbox Code Playgroud)

这是我的实体:

  public class AccessLevel : Entity
{
    public int RoleId { get;  set; }
    public Access Access { get;  set; }
    public Role Role { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

实体类型“访问”需要定义一个主键。如果您打算使用无键实体类型,请调用“HasNoKey()”。

但它Access是值对象,它不能有一个 id 。我怎么解决这个问题 ???

Joh*_*lay 11

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

OnModelCreating您将执行以下操作:

modelBuilder.Entity<AccessLevel>().OwnsOne(x => x.Access);
Run Code Online (Sandbox Code Playgroud)

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


Mau*_*rez 6

如果您使用模型搭建 .net 控制器,并且您收到此错误

实体类型“访问”需要定义一个主键。如果您打算使用无键实体类型调用“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; }
}
Run Code Online (Sandbox Code Playgroud)

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

public class GameStats {
    [Key]
    public String playerName {set; get;}
    public int gamesWon {set; get;}
}
Run Code Online (Sandbox Code Playgroud)

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

[Keyless]
public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

取自