【问题标题】:One to one relation between two abstract class in EF CoreEF Core 中两个抽象类之间的一对一关系
【发布时间】:2021-08-24 11:26:39
【问题描述】:

我在为两个抽象类创建一对一关系时遇到问题。每个类都有一个表和鉴别器。

类是:

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

我的映射是:

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

现在,我的问题是当我为 ValuationResult 表添加迁移 EF 创建牵引外键时

我想在 ValuationResult 表中有一个外键。 实际上,我希望 ValuationBase 与 ValuationResult 具有一对一的关系。这意味着我只想要两张桌子。 每个评估驱动的类都必须有一个其类型在泛型中定义的 ValuationResult。

我该如何解决这个问题?

【问题讨论】:

    标签: .net entity-framework asp.net-core entity-framework-core ef-core-2.2


    【解决方案1】:

    您已经声明了两个不同的实体关系(尽管它们都继承自同一个基础)。这就是 EF 创建两个外键的原因。

    除非有一些不为人知的理由将该通用层保留在继承结构中,否则我将删除它并将结果链接放在基类上。

    同样,除非有一些不为人知的理由来保留类型的枚举 (ValuationType),否则只需使用类类型:

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

    我会将实体重构为:

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

    然后配置:

    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)
        {
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-07-15
      • 1970-01-01
      • 2021-07-21
      • 2021-06-25
      • 1970-01-01
      • 2019-07-25
      • 1970-01-01
      • 2022-01-21
      • 2017-10-26
      相关资源
      最近更新 更多