Home > Blockchain >  How do you map subclass properties to columns in Table per Hierarchy?
How do you map subclass properties to columns in Table per Hierarchy?

Time:12-27

I have a TPH situation where I have an abstract base class and 8 derived classes from it by using a discriminator. Two of them share a list of sub classes.

 public abstract class StepBase : FullAuditedEntity<Guid>
    {
        public int Order { get; set; }
        public StepType StepType { get; set; }
    }

The thing is I have two types which shares a SubClass

 public class DestinationVesselStep : StepBase
    {
        public virtual List<DestinationVessel> VesselsDestination { get; set; }
    }
 public class LiquidNitrogenStep : StepBase
    {
        public virtual List<DestinationVessel> DestinationsBoxes { get; set; }
    }
    private static void ConfigureVesselsStep(ModelBuilder builder)
    {
        builder.Entity<DestinationVesselStep>(b =>
        {
            //Properties
            b.HasMany(p => p.VesselsDestination).WithOne().HasForeignKey(x => x.StepId);
        });
    }

    private static void ConfigureLiquidNitrogenStep(ModelBuilder builder)
    {
        builder.Entity<LiquidNitrogenStep>(b =>
        {
            //Properties
            b.HasMany(p => p.DestinationsBoxes).WithOne().HasForeignKey(x => x.StepId);
        });
    }

But when I request a LiquidNitrogenStep with two or more destinationBoxes I get the following error: System.InvalidOperationException : Sequence contains more than one element.

it works fine if I only have one destinationBox

I am expecting to get a LiquidNitrogenStep with all its destination boxes, the error do not happnd with DestinationVesselStep

CodePudding user response:

DestinationVessel.StepId can't refer to both a DestinationVesselStep and LiquidNitrogenStep.

So either add separate foreign keys to DestinationVessel, eg LiquidNitrogenStepId, and DestinationVesselStepId, or make the relationships many-to-many, which uses separate linking tables for each relationship, instead of putting foreign keys on the target Entity.

private static void ConfigureVesselsStep(ModelBuilder builder)
{
    builder.Entity<DestinationVesselStep>(b =>
    {
        //Properties
        b.HasMany(p => p.VesselsDestination).WithMany( d => d.DestinationSteps);
    });
}

private static void ConfigureLiquidNitrogenStep(ModelBuilder builder)
{
    builder.Entity<LiquidNitrogenStep>(b =>
    {
        //Properties
        b.HasMany(p => p.DestinationsBoxes).WithMany(d => d.LiquidNitrogenSteps);
    });
}

CodePudding user response:

It seems that you are using Entity Framework Core to configure your database and you are experiencing an error when trying to retrieve a LiquidNitrogenStep entity with multiple destination boxes.

There are a few things you could try to troubleshoot this issue:

Make sure that the StepId property in the DestinationVessel and DestinationBox entities is correctly mapped as a foreign key to the StepBase table.

Check if you have set the StepType property in the DestinationVesselStep and LiquidNitrogenStep entities to the correct enum value. This is important because the StepType is used as a discriminator to determine which derived class a row in the StepBase table belongs to.

Make sure that you are correctly using the Include method in your LINQ query to eager-load the VesselsDestination or DestinationsBoxes navigation properties.

var step = await _context.StepBase
    .Include(s => s.VesselsDestination)
    .SingleOrDefaultAsync(s => s.Id == stepId);

If you are using the SingleOrDefaultAsync method to retrieve the LiquidNitrogenStep entity, make sure that there is only one row in the database that matches the specified condition. If there are multiple rows, the SingleOrDefaultAsync method will throw an exception. I hope these suggestions help you troubleshoot the issue. Let me know if you have any further questions or if you need additional assistance.

  • Related