1

如果我有以下代码生成我的数据库,它会将 TankComponent 表中的外键分配给 Asset 表,而不是 Tank 表。有人可以解释为什么吗?我是否需要关闭 Fluent API 中的特定约定或更改?真的只看列名吗?

[Table("Asset")]
public abstract class Asset
{
    [Key]
    public int AssetId { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }
}


[Table("Tank")]
public class Tank : Asset
{
    public Tank()
    {
        this.TankCompnents = new Collection<TankComponent>();
    }

    public int TankField1 { get; set; }

    public ICollection<TankComponent> TankCompnents { get; set; }

    [NotMapped]
    public IEnumerable<Floor> Floors { get { return this.TankCompnents.OfType<Floor>(); } }
}


[Table("TankComponent")]
public abstract class TankComponent
{
    [Key]
    public int TankComponentId { get; set; }

    [ForeignKey("Tank")]
    public int AssetId { get; set; }
    public Tank Tank { get; set; }

    public string Name { get; set; }
}

//forgot this in initial post
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<Tank>()
    .Map(m =>
    {
        m.Properties(a => new { a.AssetId, a.Name, a.Description });
        m.Requires("AssetType").HasValue(1);
        m.ToTable("Asset");
    })
    .Map(m =>
        {
            m.Properties(t => new { t.AssetId, t.TankField1 });
            m.ToTable("Tank");
        });
}
4

1 回答 1

0

这个映射线...

m.Requires("AssetType").HasValue(1);

...并且您的评论似乎表明您可能误解了 Table-Per-Type (TPT) 继承的工作原理。

EF 不需要基类表中的特定列Asset来检测具有给定主键值的实体的实际类型是什么 - 除非您使用 Table-Per-Hierarchy (TPH) 继承映射(即没有[Table]在您的实体上具有属性)。对于 TPH,一个特定的列 - 鉴别器 - 确实需要区分类型,因为继承树中所有实体的所有属性都将存储在单个表中。如果您没有明确指定鉴别器 - 比如AssetType- EF 将创建一个Discriminator默认调用的列。

现在,TPT 是一个不同的故事。如果您查询具有其他派生实体的实体 - 例如...

var asset = context.Assets.First();

SELECT TOP(1) * FROM ASSETS...EF 不仅会像单独在基表上一样创建 SQL 查询,而且会创建一个 - 可能非常复杂的 - 查询,其中包含许多LEFT OUTER JOIN属于所有可能派生实体的许多其他表。这个查询要么在Tank表中找到一行,要么不在。如果它确实找到一个 EF 将实现一个Tank对象。如果不是,它将实现一个Asset. (这里不可能是这种情况,因为Asset只是abstract暂时假设它不会abstract。)如果有Asset其他派生类型,EF 也将加入它们的表,并根据加入行的存在再次决定具体实体类型。

因此,对于 TPT,类型不是由特殊列检测的,而是由(左外部)表连接的结果检测的。

上面的行似乎以某种方式混淆了 EF。但它确实不属于 TPT 映射,我会使用 Fluent API 删除您的整个映射。

我已经测试了当您删除映射时结果是正确的 - 即 FK 关系将在TankComponentTank表(而不是Asset表)之间创建。

于 2013-05-06T20:09:38.443 回答