EF Core继承问题(HasDiscriminator)

时间:2018-06-08 17:58:26

标签: c# entity-framework entity-framework-core ef-migrations ef-core-2.1

这是父抽象类:

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

这是一个儿童抽象类:

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; }
}

这些是另一个儿童班:

public class RequestTaxi : TransportRequest
{

}
public class RequestVanet: TransportRequest
{

}
 public class RequestWomenTaxi : TransportRequest
{

}
 public class RequestMotorCycle: TransportRequest
{

}
public class RequestLuxaryTaxi: TransportRequest
{

}

这是我的ApplicationDBContext类相关代码:

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));

这是我的迁移课程:

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

并且每五个孩子班重复一次?

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

我怎么才能只有一个DirectionPoints呢?

1 个答案:

答案 0 :(得分:3)

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

EF Core文档的Including & Excluding Types部分解释了哪些类被标识为实体

  

按照惯例,在您的上下文的DbSet属性中公开的类型包含在您的模型中。此外,还包括OnModelCreating方法中提到的类型。最后,通过递归浏览已发现类型的导航属性找到的任何类型也包含在模型中。

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

要解决这个问题,只需提及&#34;提及&#34;它在OnModelCreating

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