Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix: The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical?

I am using Entity Framework 4.3.1 against a SQL Server 2012 database and I am using the POCO approach. I am getting the following error and I am wondering if anyone can explain how to fix it:

ModelValidationException

One or more validation errors were detected during model generation: \tSystem.Data.Entity.Edm.EdmAssociationConstraint: : The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical.

There is no InnerException available for any further information.

I cannot change the database schema and it is a little odd, but here it is...

  • ** are the primary key (notice I have composite primary keys)
  • (FK) Denotes a foreign key

Here are the tables (if it helps I can post the SQL to generate them but I do not think the tables are actually the problem as the exception is in the validation of the model):

One - **OneId int not null **TwoId int not null (FK) **ThreeId int not null (FK) Name nvarchar(50) not null  Two - **TwoId int not null **ThreeId int not null (FK) Name nvarchar(50) not null  Three - **ThreeId not null Name nvarchar(50) not null 

Here are the entities (notice that I am including the foreign keys in the model but other than that pretty standard):

public class Three {     public int ThreeId { get; set; }     public string Name { get; set; }     public virtual ICollection<Two> Twos { get; private set; }     public virtual ICollection<One> Ones { get; private set; }      public void AddOne(One one)     {         if (one == null)             throw new ArgumentNullException("two");          if (Ones == null)             Ones = new List<One>();          if (!Ones.Contains(one))             Ones.Add(one);          one.Three = this;     }      public void AddTwo(Two two)     {         if (two == null)             throw new ArgumentNullException("two");          if (Twos == null)             Twos = new List<Two>();          if (!Twos.Contains(two))             Twos.Add(two);          two.Three = this;     } }  public class Two {     public int TwoId { get; set; }     public int ThreeId { get; set; }     public string Name { get; set; }     public virtual Three Three { get; set; }     public virtual ICollection<One> Ones { get; private set; }      public void AddOne(One one)     {         if (one == null)             throw new ArgumentNullException("two");          if (Ones == null)             Ones = new List<One>();          if (!Ones.Contains(one))             Ones.Add(one);          one.Two = this;     } }  public class One {     public int OneId { get; set; }     public int TwoId { get; set; }     public int ThreeId { get; set; }     public virtual Two Two { get; set; }     public virtual Three Three { get; set; } } 

And here is the data context:

public class DbCtx : DbContext {     public DbCtx(string connectionString)         : base(connectionString)     {         Ones = Set<One>();         Twos = Set<Two>();         Threes = Set<Three>();     }      public DbSet<One> Ones { get; private set; }     public DbSet<Two> Twos { get; private set; }     public DbSet<Three> Threes { get; private set; }      protected override void OnModelCreating(DbModelBuilder modelBuilder)     {         var one = modelBuilder.Entity<One>();         one.ToTable("One");          one.HasKey(d => new                             {                                 d.OneId,                                 d.TwoId,                                 d.ThreeId                             });          one.Property(d => d.OneId)             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);          one.HasRequired(t => t.Two)             .WithMany(s => s.Ones)             .HasForeignKey(t => t.TwoId);          one.HasRequired(t => t.Three)             .WithMany(s => s.Ones)             .HasForeignKey(t => t.ThreeId);          var two = modelBuilder.Entity<Two>();         two.ToTable("Two");          two.HasKey(d => new                             {                                 d.TwoId,                                 d.ThreeId                             });          two.Property(p => p.TwoId)             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);          two.HasRequired(t => t.Three)             .WithMany(s => s.Twos)             .HasForeignKey(t => t.ThreeId);          var three = modelBuilder.Entity<Three>();         three.ToTable("Three");         three.HasKey(s => s.ThreeId);          three.Property(p => p.ThreeId)             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);          base.OnModelCreating(modelBuilder);     } } 

Finally, this is a snippet of code to cause the exception:

using (var ctx = new DbCtx(@".....")) {     Console.WriteLine(ctx.Twos.Count()); } 
like image 625
kmp Avatar asked Aug 01 '12 07:08

kmp


1 Answers

The reason for the error are incorrectly configured relations in your model. This is not correct:

    one.HasRequired(t => t.Two)         .WithMany(s => s.Ones)         .HasForeignKey(t => t.TwoId);      one.HasRequired(t => t.Three)         .WithMany(s => s.Ones)         .HasForeignKey(t => t.ThreeId); 

It should be:

    one.HasRequired(t => t.Two)         .WithMany(s => s.Ones)         .HasForeignKey(t => new { t.TwoId, t.ThreeId }); 

Because dependent's FK must contain all columns of principal PK. You must also remove navigation property from Three to One.

like image 91
Ladislav Mrnka Avatar answered Sep 21 '22 06:09

Ladislav Mrnka