【发布时间】:2020-09-02 09:26:32
【问题描述】:
假设我有以下对象
- 武器
- 剑
- 步枪
- 弓
我想要以下结构。
- 武器只能是其中之一,但必须至少是 1 个。
- 所有武器必须存放在同一个地方。
- 所有武器类型都必须存储在各自对应的表格中,例如剑、步枪、弓。 (不重复数据)
这就是我所做的。
我创建了一个名为IWeapon 的接口,看起来像这样
public interface IWeapon
{
public int Id { get; set; }
[Key, ForeignKey("Weapon")]
public int WeaponId { get; set; }
public Weapon Weapon{ get; set; }
}
这是我的其他课程
public class Weapon
{
public int Id { get; set; }
public decimal Damage { get; set; }
public IWeapon ActualWeapon { get; set; }
}
public class Sword : IWeapon
{
public int Id { get; set; }
[Key, ForeignKey("Weapon")]
public int WeaponId { get; set; }
public Weapon Weapon{ get; set; }
//other properties and methods
}
//same for Rifle and Bow
定义我的结构后,我尝试让它在 Entity Framework Core 中工作。
我在我的 dbcontext 中执行了以下操作来设置 1 对 1 关系
public DbSet<Weapon> Weapons { get; set; }
public DbSet<Sword> Swords { get; set; }
public DbSet<Rifle> Rifles { get; set; }
public DbSet<Bow> Bows { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Weapon>()
.HasOne(w => (Sword)w.ActualWeapon)
.WithOne()
.HasForeignKey<Sword>(WeaponT => WeaponT.WeaponId);
modelBuilder.Entity<Weapon>()
.HasOne(w => (Rifle)w.ActualWeapon)
.WithOne()
.HasForeignKey<Rifle>(WeaponT => WeaponT.WeaponId);
modelBuilder.Entity<Weapon>()
.HasOne(w => (Bow)w.ActualWeapon)
.WithOne()
.HasForeignKey<Bow>(WeaponT => WeaponT.WeaponId);
}
我面临的问题是只有最后创建的关系有效。所以在这种情况下,弓会起作用,假设它是因为所有关系都进入同一列,那么它不知道要影响哪一个,并将其基于我对模型构建器所做的铸造
有没有办法为同一列设置多个 1 到 0..1 关系,同时仍保持大部分结构
【问题讨论】:
-
你的桌子看起来很奇怪。为什么不只是 1 个表“Weapon”,而该表有名为“WeaponType”的列(弓、剑等)?如果想要拥有不同类型的剑,请创建另一个新表“WeaponType”,其中包含“ID”、“WeaponID”、“名称”(龙剑、蛇剑...)、“伤害”。
-
目前 EF Core 不支持(无法映射)此类模型。您必须重新审视您的设计,或将接口替换为抽象类,并且 (1) 删除单独的表要求并使用现有的 TPH 映射或 (2) 等待 EF Core 5.0 和 TPT 映射
-
遗憾的是,由于它与其他系统相互关联,因此该设计非常锁定。这是我可以在不泄露 IP 的情况下解释的最简单方法,但保留完整结构以提供可解决的问题。在我的情况下,每种武器类型都由不同的公司管理
-
@IvanStoev 你知道 TPT 映射什么时候完成吗?我在 TPT 上阅读,也认为它可以解决我的问题
-
EF Core 5.0 是 scheduled for November 2020。 TPT 已在Preview 8 中提供。