none
Code first ef6 self referencing many-to-many with payload RRS feed

  • Question

  • I'm having a problem figering out how to configure a self referencing many-to-many with payload in fluent api.

    **The classes** 

      public class DragerType
        {
            [Key]
            public int DragerTypeID { get; set; }
            [Index()]
            public eDragerType Type { get; set; }
            public string Omschrijving { get; set; }
            public double? MaxGewicht { get; set; }
            public int? Hoogte { get; set; }
            public int? Diepte { get; set; }
            public int? Breedte { get; set; }
            public virtual ICollection<ConfDragerType> Children { get; set; }     
        }
    
        public class ConfDragerType
        {
            [Key,Column(Order = 0)]
            public int ParentID { get; set; }
            public virtual DragerType ParentDragerType { get; set; }
            [Key, Column(Order = 1)]
            public int ChildID { get; set; }
            public virtual DragerType ChildDragerType { get; set; }
            public int? Count { get; set; }
        }


    **The Context**

     public virtual DbSet<DragerType> DragerTypes { get; set; }
    
        modelBuilder.Entity<ConfDragerType>()
              .HasRequired(p => p.ChildDragerType)
              .WithMany(m => m.Children)
              .HasForeignKey(f => f.ChildID);
    
        modelBuilder.Entity<ConfDragerType>()
              .HasRequired(r => r.ParentDragerType)
              .WithMany()
              .HasForeignKey(f => f.ParentID)
              .WillCascadeOnDelete(false);


    **Now my database diagram looks fine**

    I have two one to many relationships from DragerType to ConfDragerType (Dragertype in both cases has to key)

    **Code**
    But when I try to at a child to a parent DragerType like this        

    parent.Children.Add(new ConfDragerType() {ChildDragerType = child, Count = 20});
        unitOfWork.DragerTypes.Update(p);
        unitOfWork.Commit();


    then I get the error: 
        InvalidOperationException: *{Multiplicity constraint violated. The role  'ConfDragerType_ChildDragerType_Target' of the relationship  'Optima.Data.Context.ConfDragerType_ChildDragerType' has multiplicity 1 or 0..1."}*

    thx

    • Moved by CoolDadTx Thursday, June 16, 2016 4:40 PM EF related
    Thursday, June 16, 2016 10:24 AM

Answers

  • Thank you for the anwer

    I now have it solved. I tried something like you suggested before but I was the onmodelcreating code was wrong. I used:

    modelBuilder.Entity<ConfDragerType>()
                            .HasRequired<DragerType>(c => c.ParentDragerType)
                            .WithMany(d => d.Parents)
                            .WillCascadeOnDelete(true);

    • Marked as answer by das_stein Friday, June 17, 2016 11:14 AM
    Friday, June 17, 2016 11:13 AM

All replies

  • I'm having a problem figering out how to configure a self referencing many-to-many with payload in fluent api.

    **The classes** 

      public class DragerType
        {
            [Key]
            public int DragerTypeID { get; set; }
            [Index()]
            public eDragerType Type { get; set; }
            public string Omschrijving { get; set; }
            public double? MaxGewicht { get; set; }
            public int? Hoogte { get; set; }
            public int? Diepte { get; set; }
            public int? Breedte { get; set; }
            public virtual ICollection<ConfDragerType> Children { get; set; }     
        }
    
        public class ConfDragerType
        {
            [Key,Column(Order = 0)]
            public int ParentID { get; set; }
            public virtual DragerType ParentDragerType { get; set; }
            [Key, Column(Order = 1)]
            public int ChildID { get; set; }
            public virtual DragerType ChildDragerType { get; set; }
            public int? Count { get; set; }
        }


    **The Context**

     public virtual DbSet<DragerType> DragerTypes { get; set; }
    
        modelBuilder.Entity<ConfDragerType>()
              .HasRequired(p => p.ChildDragerType)
              .WithMany(m => m.Children)
              .HasForeignKey(f => f.ChildID);
    
        modelBuilder.Entity<ConfDragerType>()
              .HasRequired(r => r.ParentDragerType)
              .WithMany()
              .HasForeignKey(f => f.ParentID)
              .WillCascadeOnDelete(false);

    **Now my database diagram looks fine**

    I have two one to many relationships from DragerType to ConfDragerType (Dragertype in both cases has to key)

    **Code**
    But when I try to at a child to a parent DragerType like this        

    parent.Children.Add(new ConfDragerType() {ChildDragerType = child, Count = 20});
        unitOfWork.DragerTypes.Update(p);
        unitOfWork.Commit();


    then I get the error: 
        InvalidOperationException: *{Multiplicity constraint violated. The role  'ConfDragerType_ChildDragerType_Target' of the relationship  'Optima.Data.Context.ConfDragerType_ChildDragerType' has multiplicity 1 or 0..1."}*

    thx

    Thursday, June 16, 2016 11:36 AM
  • Before mapping the tables, figure out how you want the hierarcy to work.  Walk it through like:

    "A DragerType has a collection of ConfDragerType, and every ConfDragerType has a parent DraggerType"

    "A ConfDragerType has a collection of ConfDragerType, and some ConfDragerType have a parent ConfDragerType"

    If this is what you want then ConfDraggerType is missing its child collection of ConfDragerType and parent association to the parent ConfDragerType.

    David


    David http://blogs.msdn.com/b/dbrowne/


    Thursday, June 16, 2016 1:43 PM
  • I don't exactly understand what you mean, the main goal is that I want a many to many relationship of DragerType but is has to have a payload parameter 'count'. This is why to ConfDragerType is used.

    thx

    Thursday, June 16, 2016 2:08 PM
  • Many-to-many with extra properties on the linking table would look something like this:

        public class DragerType
        {
            [Key]
            public int DragerTypeID { get; set; }
            //[Index()]
            //public eDragerType Type { get; set; }
            public string Omschrijving { get; set; }
            public double? MaxGewicht { get; set; }
            public int? Hoogte { get; set; }
            public int? Diepte { get; set; }
            public int? Breedte { get; set; }
            public virtual ICollection<ConfDragerType> ConfDragerTypeChildren { get; set; } = new HashSet<ConfDragerType>();
            public virtual ICollection<ConfDragerType> ConfDragerTypeParents { get; set; } = new HashSet<ConfDragerType>();
    
        }
    
        public class ConfDragerType
        {
            [Key, Column(Order = 0)]
            public int ParentID { get; set; }
            
            [Key, Column(Order = 1)]
            public int ChildID { get; set; }
    
    
            [ForeignKey("ParentID")]
            public virtual DragerType ParentDragerType { get; set; }
    
            [ForeignKey("ChildID")]
            public virtual DragerType ChildDragerType { get; set; }
            public int? Count { get; set; }
        }
    
        class DraggerDb : DbContext
        {
            public DbSet<DragerType> DragerTypes  { get; set; }
            public DbSet<ConfDragerType>  ConfDragerTypes { get; set; }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Entity<ConfDragerType>()
                            .HasRequired<DragerType>(c => c.ParentDragerType)
                            .WithMany(d => d.ConfDragerTypeChildren)
                            .WillCascadeOnDelete(true);
    
                modelBuilder.Entity<ConfDragerType>()
                            .HasRequired<DragerType>(c => c.ChildDragerType)
                            .WithMany(d => d.ConfDragerTypeParents)
                            .WillCascadeOnDelete(false);
                
                base.OnModelCreating(modelBuilder);
            }
        }
    
    David


    David http://blogs.msdn.com/b/dbrowne/

    Thursday, June 16, 2016 4:39 PM
  • Hi das_stein,

    Based on your code snippet, I create a demo and reproduce your issue on my side, it seems that you need to useChildIDin stead of related navigate property. likethis:

    parent.Children.Add(new ConfDragerType() { ParentID = child.DragerTypeID, ChildID = parent.DragerTypeID, Count = 20 });

    Best regards,

    Cole Wu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, June 17, 2016 2:37 AM
    Moderator
  • Thank you for the anwer

    I now have it solved. I tried something like you suggested before but I was the onmodelcreating code was wrong. I used:

    modelBuilder.Entity<ConfDragerType>()
                            .HasRequired<DragerType>(c => c.ParentDragerType)
                            .WithMany(d => d.Parents)
                            .WillCascadeOnDelete(true);

    • Marked as answer by das_stein Friday, June 17, 2016 11:14 AM
    Friday, June 17, 2016 11:13 AM