EF Core 5 TPT - 具有不同 ID 名称的继承对象

Posted

技术标签:

【中文标题】EF Core 5 TPT - 具有不同 ID 名称的继承对象【英文标题】:EF Core 5 TPT - Inherited object with different ID name 【发布时间】:2021-07-27 19:50:19 【问题描述】:

通常应用程序是由 ID 字段构成的,只是在数据库中将其命名为“ID”。但是在我工作的应用程序中不遵循这个约定。我有两个表,它们被规范化为用继承表示。主表称为“Entity”,其主键称为“IdEntity”。而另一个从Entity继承的表叫做“Source”,它的主键叫做“IdSource”,但它不是身份,是Entity.IdEntity的外键。

在当前应用程序(webforms)中它工作正常,我需要用 EF Core 和 .NET Core 5 在新应用程序上表示它。如果我用 _context.Entities.Find(id) 列出它工作正常,但是当我执行 _context.Sources.Find(id) 时,同样不适用。

我的课程定义为:

实体

public class Entity

    [Column("IdEntity"), Key]
    public int Id  get; set; 

来源

public class Source : Entity

    [Column("IdSource"), Key]
    public int Id  get; set; 

请注意,我在 Source 中明确指定了 ID 列。但是当我对代码运行查询时,我收到错误消息:“Microsoft.Data.SqlClient.SqlException: 'Invalid column name 'IdEntity'.'”

我使用 SQL Server Profiler 跟踪执行,并意识到 EF 正在创建查询,只是忽略 Source 中的列标题 IdSource 并插入 IdEntity,创建类似这样的内容:

select * -- All fields
from Entity t
inner join Source t0 on t.IdEntity = t0.IdEntity 
/* Note that it is inserting t0.IdEntity, but the alias for t0 is for Source, that there are no fields named IdEntity */

如何明确告诉 EF Core 主键是 IdSource 而不是 IdEntity for Source?

编辑:这个新应用程序是数据库优先的,它是强制性的!我正在尝试从基于 Webforms 的现有应用程序迁移。

【问题讨论】:

Source.IdEntity 可能是基于导航属性自动创建的阴影列?还有,部署新应用时不能迁移数据库? 【参考方案1】:

尝试使用fluent API配置模型

这样您就可以轻松地为每个实体类执行类似这样的代码:

    public class SourceEntityTypeConfiguration : IEntityTypeConfiguration<Source>
    
        public void Configure(EntityTypeBuilder<Source> builder)
        
            builder
                .Property(b => b.Id)
                .HasColumnName("IdSource");               
        
    

【讨论】:

我部署了这个 sn-p(必须添加 Microsoft.EntityFrameworkCore.Relational),但结果相同。 如果您使用此代码,您必须在源类和实体类中删除 id 上面的注释,您尝试过吗?【参考方案2】:

我不确定这个问题是否仍然与您相关,但也许这些信息会有所帮助:https://github.com/dotnet/efcore/issues/19811。简而言之,具有不同 ID-column-name 的 TPT 尚不可行(截至 2021 年 12 月 6 日)

【讨论】:

以上是关于EF Core 5 TPT - 具有不同 ID 名称的继承对象的主要内容,如果未能解决你的问题,请参考以下文章

EF Core 5 TPT 和身份 (CRUD)

具有不同列名的 EF Core 5 HasForeignKey 问题

ef core 如何一次从具有外键的不同表中获取数据? (数据库优先)

使用 EF Code First 继承 – 每个类型的表 (TPT)

如何在使用 TPT 层次结构时首先在 EF 代码中实现并发

Inheritance with EF Code First: Part 2 – Table per Type (TPT)