c# - Entity Framework 在子类上是唯一的

标签 c# asp.net entity-framework entity-framework-core

我对 Entity Framework 中应该如何处理这种情况感到困惑。

我有一个角色基类:

public class Character
{
    [Key]
    public Guid Id { get; set; }
    public Realm Realm { get; set; }
    public Guid RealmId { get; set; }
    public string Name { get; set; }
}

角色有名字并绑定(bind)到领域。

玩家控制的角色绝对是角色。它绑定(bind)到玩家/用户:

public class PlayerCharacter : Character
{        
    public User User { get; set; }
    public Guid UserId { get; set; }
}

NPC 也是一个角色:它不需要具有 MCVE 的任何属性

public class Npc : Character { }

现在,很明显,您不希望在同一个领域中拥有相同名称的角色,但是您可以在一个领域中拥有任意数量的 Orcs,因此我们需要在 PlayerCharacter 上定义唯一约束,例如通过 .HasAlternateKey:

public DbSet<PlayerCharacter> Characters { get; set; }
public DbSet<Npc> Npcs { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<PlayerCharacter>()
        .HasAlternateKey("Name", "RealmId");
}

现在我们添加迁移:

$ dotnet ef migrations add 5
System.InvalidOperationException: A key cannot be configured on 
'PlayerCharacter' because it is a derived type. The key must be 
configured on the root type 'Character'.

好的,唯一索引怎么样?

modelBuilder.Entity<PlayerCharacter>()
    .HasIndex("Name", "RealmId")
    .IsUnique();

$ dotnet ef migrations add 5
Done. To undo this action, use 'ef migrations remove'

成功了!但是等等:

migrationBuilder.CreateTable(
    name: "Character",
    columns: table => new
    {
        Id = table.Column<Guid>(nullable: false),
        Discriminator = table.Column<string>(nullable: false),
        Name = table.Column<string>(nullable: true),
        RealmId = table.Column<Guid>(nullable: false),
        // other props...
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Character", x => x.Id);
        // foreign keys...
    });

migrationBuilder.CreateIndex(
    name: "IX_Character_Name_RealmId",
    table: "Character",
    columns: new[] { "Name", "RealmId" },
    unique: true);

现在玩家角色和 NPC 的名字都是独一无二的!如何仅在派生类中设置唯一性?

最佳答案

目前(EF Core 2.0.1)唯一可以做到这一点的方法是使用基于 Discriminator column 的过滤唯一索引。值(value)。

不幸的是HasFilter流畅的 API 与数据库无关。下面是 SqlServer 的配置:

modelBuilder.Entity<PlayerCharacter>()
    .HasIndex("Name", "RealmId")
    .IsUnique()
    .HasFilter($"Discriminator = '{nameof(PlayerCharacter)}'"); // <--

关于c# - Entity Framework 在子类上是唯一的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48309180/

相关文章:

c# - 使用 TPH 的 Entity Framework 多级继承

c# - Entity Framework 在哪里存储属性名称和它在 SQL 中选择的列之间的映射?

c# - 获取列表中的项目

c# - 为什么在 WPF 中显示 OpenFileDialog 会阻止我的 WPF 弹出窗口?

asp.net - 自动生成的 visual studio &lt;meta&gt; 标签有什么用吗

asp.net - 上传我的 ASP.NET 网站?

c# - 如何索引和搜索 Lucene.NET 中的日期时间字段?

c# - 使用 C# 的 SerialPort 类将命令传递到 Com 端口

c# - 如何在代码隐藏中访问aspx控件?

c# - 自动生成的实体类中缺少导航属性