简体   繁体   English

EF Core 中两个抽象 class 之间的一对一关系

[英]One to one relation between two abstract class in EF Core

I have a problem to create one to one relation for two abstract class. Each class has one table and discriminator.我在为两个抽象 class 创建一对一关系时遇到问题。每个 class 都有一个表和鉴别器。

Classes are:类是:

public abstract class ValuationBase
{
    public Guid Id { get; internal set; }
    public DateTime CreationDateTime { get; internal set; }

    public Owner Owner { get; internal set; }
}

public abstract class Valuation<TResult> : ValuationBase where TResult : ValuationResult
{
    public abstract ValuationType Type { get; }

    public abstract TResult Result { get; protected set; }
}

public class ScoringCardValuation : Valuation<ScoringCardValuationResult>
{
    .
    .
    .

    public override ScoringCardValuationResult Result { get; protected set; }

    public override ValuationType Type => ValuationType.ScoringCardValuation;
}

public class FirstChicagoValuation : Valuation<FirstChicagoValuationResult>
{
    .
    .
    .

    public override ValuationType Type => ValuationType.FirstChicagoValuation;

    public override FirstChicagoValuationResult Result { get; protected set; }
}


public abstract class ValuationResult
{
    public Guid Id { get; set; }
    public abstract ValuationType ValuationType { get; }
}

public class ScoringCardValuationResult : ValuationResult
{
    .
    .
    .

    public override ValuationType ValuationType => ValuationType.ScoringCardValuation;
}

public class FirstChicagoValuationResult : ValuationResult
{
    .
    .
    .

    public override ValuationType ValuationType => ValuationType.FirstChicagoValuation;
}

And my mapping is:我的映射是:

public class ValuationBaseMapping : IEntityTypeConfiguration<ValuationBase>
{
    public void Configure(EntityTypeBuilder<ValuationBase> builder)
    {
        builder.HasKey(c => c.Id);

        builder.HasDiscriminator()
            .HasValue<ScoringCardValuation>(nameof(ScoringCardValuation))
            .HasValue<FirstChicagoValuation>(nameof(FirstChicagoValuation));

        builder.OwnsOne(i => i.Owner);
    }
}

public class ScoringCardValuationMapping : IEntityTypeConfiguration<ScoringCardValuation>
{
    public void Configure(EntityTypeBuilder<ScoringCardValuation> builder)
    {
        builder.HasOne(c => c.Result).WithOne().HasForeignKey<ScoringCardValuationResult>("ValuationResultId");
    }
}

public class FirstChicagoValuationMapping : IEntityTypeConfiguration<FirstChicagoValuation>
{
    public void Configure(EntityTypeBuilder<FirstChicagoValuation> builder)
    {
        .
        .
        .

        builder.HasOne(c => c.Result).WithOne().HasForeignKey<FirstChicagoValuationResult>("ValuationResultId");
    }
}


public class ValuationResultMapping : IEntityTypeConfiguration<ValuationResult>
{
    public void Configure(EntityTypeBuilder<ValuationResult> builder)
    {
        builder.HasKey(c => c.Id);

        builder.HasDiscriminator()
            .HasValue<ScoringCardValuationResult>(nameof(ScoringCardValuationResult))
            .HasValue<FirstChicagoValuationResult>(nameof(FirstChicagoValuationResult));
    }
}

Now, My problem is when I add a migration EF create tow foriegn key for ValuationResult table现在,我的问题是当我添加迁移 EF 为 ValuationResult 表创建两个外键时

I want to have one foriegn key in ValuationResult table.我想在 ValuationResult 表中有一个外键。 Actually, I want ValuationBase to have a one to one relationship to ValuationResult.实际上,我希望 ValuationBase 与 ValuationResult 具有一对一的关系。 It means I just want two tables.这意味着我只想要两张桌子。 Every Valuation drived class must have a ValuationResult that its type is defined in generic.每个 Valuation 驱动的 class 都必须有一个 ValuationResult,其类型定义为泛型。

How can I fix that?我该如何解决?

You've declared two different entity relationships (notwithstanding the fact they both inherit from same base).您已经声明了两个不同的实体关系(尽管它们都继承自同一基础)。 This is why EF is creating two foreign keys.这就是 EF 创建两个外键的原因。

Unless there's some unseen reason to keep that Generic layer in the inheritance structure, then I'd remove it and put the Result link on the base class.除非有一些看不见的理由将该通用层保留在 inheritance 结构中,否则我会删除它并将结果链接放在基础 class 上。

Again, unless there's some unseen reason to keep the Enum of types (ValuationType) then just use the class type:同样,除非有一些看不见的理由保留 Enum 类型 (ValuationType),否则只需使用 class 类型:

typeof(ScoringCardValuation);
// or on an instance:
cardValuation.GetType();

I'd refactor entities to:我将实体重构为:

public abstract class ValuationBase
{
    public Guid Id { get; internal set; }
    public DateTime CreationDateTime { get; internal set; }

    public Owner Owner { get; internal set; }

    public virtual ValuationResult Result { get; internal set; }
}

public class ScoringCardValuation : ValuationBase
{
    public override ScoringCardValuationResult Result 
    { 
        get => base.Result as ScoringCardValuationResult;
        protected set => base.Result = value; 
    }
}

public class FirstChicagoValuation : Valuation<FirstChicagoValuationResult>
{
    public override FirstChicagoValuationResult Result 
    { 
        get => base.Result as FirstChicagoValuationResult;
        protected set => base.Result = value; 
    }
}

Then configure:然后配置:

public class ValuationBaseMapping : IEntityTypeConfiguration<ValuationBase>
{
    public void Configure(EntityTypeBuilder<ValuationBase> builder)
    {
        builder.HasKey(c => c.Id);

        builder.HasDiscriminator()
            .HasValue<ScoringCardValuation>(nameof(ScoringCardValuation))
            .HasValue<FirstChicagoValuation>(nameof(FirstChicagoValuation));

        builder.OwnsOne(i => i.Owner);

        builder.HasOne(c => c.Result)
            .WithOne()
            .HasForeignKey<ValuationResult>("ValuationResultId");
    }
}

public class ScoringCardValuationMapping : IEntityTypeConfiguration<ScoringCardValuation>
{
    public void Configure(EntityTypeBuilder<ScoringCardValuation> builder)
    {
    }
}

public class FirstChicagoValuationMapping : IEntityTypeConfiguration<FirstChicagoValuation>
{
    public void Configure(EntityTypeBuilder<FirstChicagoValuation> builder)
    {
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM