Skip to content

Collection on an inherited class is not included #121

@heyadamhey

Description

@heyadamhey

I have a class called BonusMatch that inherits from an abstract class called Bonus. When I save a BonusMatch entity, Detached.Mappers will see the Composition collections on Bonus but not see the collection on the BonusMatch class.

The Bonus class uses an enum Discriminator.

The entity is:

public abstract class Bonus
{
....
	private IList<BonusAlert> _alerts;
        public virtual IList<BonusAlert> Alerts
        {
            get { return _alerts; }
            set { _alerts = value; }
        }
...

}

public partial class BonusMatch : Bonus
{
...
	private IList<BonusMatchTier> _tiers;
        public virtual IList<BonusMatchTier> Tiers
		{
			get { return _tiers; }
			set { _tiers = value; }
		}
...
}

My EF mapping is


protected override void OnModelCreating(ModelBuilder modelBuilder)
{
            modelBuilder.ApplyConfiguration(new Configurations.BonusConfiguration());
            modelBuilder.Entity<BonusMatch>()
				.HasMany(b => b.Tiers)
				.WithOne(t => t.Bonus)
				.HasConstraintName("FK_BonusMatchTier_Bonus")
				.OnDelete(DeleteBehavior.Cascade);
}

...

public void Configure(EntityTypeBuilder<Bonus> modelBuilder)
{
            modelBuilder.ToTable("Bonus");
            modelBuilder.HasDiscriminator(d => d.SecondaryBonusType)
				.HasValue<BonusMatch>(BonusTypes.Match)
				.HasValue<BonusNoDeposit>(BonusTypes.NoDeposit)
				.HasValue<BonusFreeplay>(BonusTypes.Freeplay)
				.HasValue<BonusPostWager>(BonusTypes.PostWager)
				.HasValue<BonusCashback>(BonusTypes.Cashback)
				.HasValue<BonusSportsbookCashback>(BonusTypes.SportsbookCashback)
				.HasValue<BonusSportsbookFreeBet>(BonusTypes.SportsbookFreeBet)
				.HasValue<BonusSportsbookMatch>(BonusTypes.SportsbookMatch);

            modelBuilder
                .HasMany(b => b.Alerts)
                .WithOne()
                .HasConstraintName("FK_BonusAlert_Bonus")
                .OnDelete(DeleteBehavior.Cascade);
}

My Detached.Mappers configuration is as follows:

                        profileOptions.Type<Bonus>() // Not sure if this block is necessary
                            .Abstract(true)
                            .Discriminator(b => b.SecondaryBonusType)
                            .HasValue<BonusMatch>(BonusTypes.Match)
                            .HasValue<BonusNoDeposit>(BonusTypes.NoDeposit)
                            .HasValue<BonusFreeplay>(BonusTypes.Freeplay)
                            .HasValue<BonusPostWager>(BonusTypes.PostWager)
                            .HasValue<BonusCashback>(BonusTypes.Cashback)
                            .HasValue<BonusSportsbookCashback>(BonusTypes.SportsbookCashback)
                            .HasValue<BonusSportsbookFreeBet>(BonusTypes.SportsbookFreeBet)
                            .HasValue<BonusSportsbookMatch>(BonusTypes.SportsbookMatch);

                        profileOptions.Type<Bonus>()
				.Member(b => b.DateUpdated).Exclude()
                            .Member(b => b.DateAdded).Exclude()
                            .Member(b => b.Guid).Exclude()
                            .Member(b => b.Casino).Parent()
                            .Member(b => b.SpecificCountries).Aggregation()
                            .Member(b => b.ProhibitedCountries).Aggregation()
                            .Member(b => b.SpecificWebsiteClients).Aggregation()
                            .Member(b => b.AllowedUSStates).Aggregation()
                            .Member(b => b.SpecificUSStates).Aggregation()
                            .Member(b => b.BonusCasinoCurrencies).Composition()
                            .Member(b => b.Alerts).Composition()
                            .Member(b => b.TrackerLinks).Composition()
                            .Member(b => b.GameEligibilities).Composition()
                            .Member(b => b.BonusSignificantTerms).Composition();
							
                        // This composition appears to be ignored
                        profileOptions.Type<BonusMatch>()
                            .Member(b => b.Tiers).Composition();

When I save a BonusMatch and call _context.Map<TDomainEntity>(dto); (where TDomainEntity is a BonusMatch) I step through the Detached.Mappers code until I reach the Load method in the Loader class. The query.Load gets all of the collections on Bonus (e.g. Alerts ) but it does not generate a query to return the Tiers collection on BonusMatch so the Tiers collection is empty in the target object below:

var target = Loader.Load(dbContext, typeof(TEntity), entityOrDto);

As a result, EF's change tracker always sees the Tiers items as Added and not Unchanged or Modified

Screenshots
DTO object has two Tiers

Image

Loaded object has no Tiers. No SQL query is generated to select them
Image

Expected behavior
I expected the Composition attribute on Tiers would include the collection from the database for the change tracking, but it is not I suspect this is due to the inheritance in some way.
This configuration appears to be ignored

Desktop (please complete the following information):

  • OS: Windows 11
  • Browser: Chrome
  • Version: 135

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions