Skip to content

Self-referencing Many-to-many #915

Closed
@rachael-ross

Description

@rachael-ross

DESCRIPTION

I have an entity that can have other entities of the same type (Org) as "Clients" and "Parents" (parents can change over time) and an explicit relationship entity (OrgClient). Since the relationship entity has two properties of the same type (Org), JADNC can't, of course, automatically extrapolate the proper property it needs to create the relationship on.

STEPS TO REPRODUCE

 public class Org : Identifiable<long>
    {             
        [NotMapped]
        [HasManyThrough(nameof(OrgClients), InverseNavigation = "ClientOrg")]
        public ICollection<Org> Clients { get; set; } = new HashSet<Org>();

        [NotMapped]
        [HasManyThrough(nameof(ManagingOrgClients), InverseNavigation = "ManagingOrg")]
        public ICollection<Org> ManagingOrgs { get; set; } = new HashSet<Org>();

        public ICollection<OrgClient> OrgClients { get; set; } = new HashSet<OrgClient>();

        public ICollection<OrgClient> ManagingOrgClients { get; set; } = new HashSet<OrgClient>();
  
    }
public class OrgClient : Identifiable<long>
    {
        [Attr]
        public long ClientOrgId { get; set; }
        [HasOne]
        public virtual Org ClientOrg { get; set; }
        [Attr]
        public long ManagingOrgId { get; set; }
        [HasOne]
        public virtual Org ManagingOrg { get; set; }       
    }
 public void Configure(EntityTypeBuilder<OrgClient> builder)
        {
            builder.HasKey(e => e.Id);            
           
            builder.HasOne(e => e.ClientOrg).WithMany(d => d.OrgClients).HasForeignKey(d => d.ManagingOrgId).IsRequired().OnDelete(DeleteBehavior.NoAction);
            builder.HasOne(e => e.ManagingOrg).WithMany(d => d.ManagingOrgClients).HasForeignKey(d => d.ClientOrgId).IsRequired().OnDelete(DeleteBehavior.NoAction);
        }

EXPECTED BEHAVIOR

I thought specifying the InverseNavigation property would take care of that, but it appears that value is being ignored when building the relationships.

ACTUAL BEHAVIOR

I was experiencing an exception being thrown in ResourceGraphBuilder::GetRelationships() on this line:

hasManyThroughAttribute.LeftProperty = throughProperties.SingleOrDefault(x => x.PropertyType.IsAssignableFrom(resourceType))
                            ?? throw new InvalidConfigurationException($"{throughType} does not contain a navigation property to type {resourceType}");

Since OrgClient has two properties of the same type (Org), the SingleOrDefault is choking.

Locally, I've added logic to examine the InverseNavigation property of the HasManyThroughAttribute, if it's been assigned, and it seems all is working fine with that, but I've not made it through tests for all CRUD operations yet. I'm not sure if there are further considerations I need to make for this, if this is a bug, a feature request or I'm just simply missing something?

VERSIONS USED

  • JsonApiDotNetCore version: master as of 11/15/2020
  • ASP.NET Core version: 3.1
  • Entity Framework Core version: 3.1.10
  • Database provider: Sql Server

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions