EF Core 继承问题(HasDiscriminator)

EF Core Inheritance issue (HasDiscriminator)

这是 parent 摘要 class :

public enum RequestType
{
    TaxiRequester,
    WomenTaxiRequester,
    LuxaryTaxiRequester,
    MotrCycleRequester,
    VanetRequester
}
public enum PaymentType
{
    Cash = 0,
    Credit=1,
    Free=2
}

public abstract class Request
{
    protected Request()
    {
        PersonsRequests = new HashSet<PersonRequest>();
        WorkerRequestNotification= new HashSet<WorkerRequestNotification>();
    }

    #region EFValidator

    [Required]
    [Key]
    #endregion

    public Guid RequestId { get; set; }
    #region EFValidator

    [Required]

    #endregion

    public string CodeSafar { get; set; }

    #region EFValidator

    [Required]

    #endregion

    public DateTime RequestDate { get; set; }
    #region EFValidator

    [Required]

    #endregion

    public DateTime RequestWorkDate { get; set; }

    #region EFValidator

    [Column(TypeName = "nvarchar(max)")]

    #endregion

    public string DestinationAddress { get; set; }
    #region EFValidator

    [Column(TypeName = "nvarchar(max)")]
    [Required]
    #endregion

    public string DestinationLat { get; set; }
    #region EFValidator

    [Column(TypeName = "nvarchar(max)")]
    [Required]
    #endregion

    public string DestinationLon { get; set; }
    #region EFValidator

    [Required]

    #endregion
    public DateTime ApproveDate { get; set; }
    public DateTime DoneDate { get; set; }
    #region EFValidator

    [Required]

    #endregion

    public long Price { get; set; }
    #region EFValidator

    [Required]

    #endregion

    public Status Status { get; set; }
    #region EFValidator

    [Required]

    #endregion

    public PaymentType PaymentType { get; set; }

    #region EFRelation
    public virtual ICollection<PersonRequest> PersonsRequests { get; set; }
    public virtual ICollection<WorkerRequestNotification> WorkerRequestNotification { get; set; }
    public virtual ICollection<Chat> Chats { get; set; }

    #endregion

    #region RatingRelations

    public virtual Rating Rating { get; set; }

    #endregion

这是一个 child 摘要 class :

public abstract class TransportRequest : Request
{
    #region EFValidator

    [Required]
    [Column(TypeName = "nvarchar(max)")]

    #endregion

    public string SourceAddress { get; set; }
    #region EFValidator

    [Required]
    [Column(TypeName = "nvarchar(max)")]

    #endregion

    public string SourceLat { get; set; }
    #region EFValidator

    [Required]
    [Column(TypeName = "nvarchar(max)")]

    #endregion

    public string SourceLon { get; set; }

    #region EFValidator

    [Required]

    #endregion

    public double Distance { get; set; }
    #region EFValidator

    [Column(TypeName = "nvarchar(max)")]

    #endregion

    public string DirectionPoints { get; set; }
}

还有另外 children classes:

public class RequestTaxi : TransportRequest
{

}
public class RequestVanet: TransportRequest
{

}
 public class RequestWomenTaxi : TransportRequest
{

}
 public class RequestMotorCycle: TransportRequest
{

}
public class RequestLuxaryTaxi: TransportRequest
{

}

这是我的 ApplicationDBContext class 相关代码:

model.Entity<Request>()
            .HasMany(p => p.Chats)
            .WithOne(b => b.Request)
            .HasForeignKey(p => p.RequestId);
        model.Entity<Request>()
            .HasMany(p => p.PersonsRequests)
            .WithOne(b => b.Request)
            .HasForeignKey(p => p.RequestId);
        model.Entity<Request>()
            .HasOne(p => p.Rating)
            .WithOne(b => b.Request)
            .HasForeignKey<Rating>(p => p.RequestId);
        model.Entity<Request>()
            .HasMany(p => p.WorkerRequestNotification)
            .WithOne(b => b.Request)
            .HasForeignKey(p => p.RequestId);

        model.Entity<Request>().Property(p => p.RequestId).ValueGeneratedOnAdd();
        model.Entity<Request>()
            .HasDiscriminator<int>(name: "Type")
            .HasValue<RequestTaxi>(value: Convert.ToInt32(value: RequestType.TaxiRequester))
            .HasValue<RequestWomenTaxi>(value: Convert.ToInt32(value: RequestType.WomenTaxiRequester))
            .HasValue<RequestLuxaryTaxi>(value: Convert.ToInt32(value: RequestType.LuxaryTaxiRequester))
            .HasValue<RequestMotorCycle>(value: Convert.ToInt32(value: RequestType.MotrCycleRequester))
            .HasValue<RequestVanet>(value: Convert.ToInt32(value: RequestType.VanetRequester));

这是我的迁移 class :

protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropIndex(
            name: "IX_Request_CodeSafar",
            table: "Request");

        migrationBuilder.AlterColumn<string>(
            name: "CodeSafar",
            table: "Request",
            nullable: false,
            oldClrType: typeof(string));

        migrationBuilder.AddColumn<string>(
            name: "RequestMotorCycle_DirectionPoints",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<double>(
            name: "RequestMotorCycle_Distance",
            table: "Request",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestMotorCycle_SourceAddress",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestMotorCycle_SourceLat",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestMotorCycle_SourceLon",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestTaxi_DirectionPoints",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<double>(
            name: "RequestTaxi_Distance",
            table: "Request",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestTaxi_SourceAddress",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestTaxi_SourceLat",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestTaxi_SourceLon",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestVanet_DirectionPoints",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<double>(
            name: "RequestVanet_Distance",
            table: "Request",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestVanet_SourceAddress",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestVanet_SourceLat",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestVanet_SourceLon",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestWomenTaxi_DirectionPoints",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<double>(
            name: "RequestWomenTaxi_Distance",
            table: "Request",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestWomenTaxi_SourceAddress",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestWomenTaxi_SourceLat",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.AddColumn<string>(
            name: "RequestWomenTaxi_SourceLon",
            table: "Request",
            type: "nvarchar(max)",
            nullable: true);

        migrationBuilder.CreateIndex(
            name: "IX_Person_ApplicationUsersId1",
            table: "Person",
            column: "ApplicationUsersId",
            unique: true);

        migrationBuilder.CreateIndex(
            name: "IX_Person_ApplicationUsersId2",
            table: "Person",
            column: "ApplicationUsersId",
            unique: true);

        migrationBuilder.CreateIndex(
            name: "IX_Person_ApplicationUsersId3",
            table: "Person",
            column: "ApplicationUsersId",
            unique: true);

        migrationBuilder.AddForeignKey(
            name: "FK_Person_ApplicationUsers_ApplicationUsersId1",
            table: "Person",
            column: "ApplicationUsersId",
            principalTable: "ApplicationUsers",
            principalColumn: "Id");

        migrationBuilder.AddForeignKey(
            name: "FK_Person_ApplicationUsers_ApplicationUsersId2",
            table: "Person",
            column: "ApplicationUsersId",
            principalTable: "ApplicationUsers",
            principalColumn: "Id");

        migrationBuilder.AddForeignKey(
            name: "FK_Person_ApplicationUsers_ApplicationUsersId3",
            table: "Person",
            column: "ApplicationUsersId",
            principalTable: "ApplicationUsers",
            principalColumn: "Id");
    }

我的问题是为什么要添加这样的专栏:

RequestMotorCycle_DirectionPoints

并每五次重复一次 children class ?

事实上我有六个 DirectionPoints 列!!!

例如,如何才能只有一个 DirectionPoints?

问题是所有这些属性都在 TransportRequest class 中定义,但 TransportRequest 未指定为 实体 (只有 Request 和最终的派生实体),因此 EF Core 假定它只是一个基础 class,并且所有派生的 classes 属性都是不同的。

EF Core 文档的 Including & Excluding Types 部分解释了 class 实体被识别为 实体 :

By convention, types that are exposed in DbSet properties on your context are included in your model. In addition, types that are mentioned in the OnModelCreating method are also included. Finally, any types that are found by recursively exploring the navigation properties of discovered types are also included in the model.

如您所见,TransportRequest 不是 DbSet,未在 OnModelCreating 中提及,也未被导航引用 属性。

要解决这个问题,只需 "mention" 它在 OnModelCreating:

// ...
model.Entity<TransportRequest>();
// ...