2012-08-01 10 views
21

Estoy utilizando Entity Framework 4.3.1 en una base de datos de SQL Server 2012 y estoy utilizando el enfoque POCO. Estoy recibiendo el siguiente error y me pregunto si alguien puede explicar cómo solucionarlo:Cómo corregirlo: ¿El número de propiedades en las Roles Dependientes y Principales en una restricción de relación debe ser idéntico?

ModelValidationException se detectaron

uno o más errores de validación durante la generación del modelo: \ tSystem.Data .Entity.Edm.EdmAssociationConstraint:: el número de propiedades en los Roles Dependiente y Principal en una restricción de relación debe ser idéntico.

No hay InnerException disponible para cualquier información adicional.

No puedo cambiar el esquema de base de datos y es un poco extraño, pero aquí está ...

  • ** son la clave principal (nótese que tengo claves primarias compuestas)
  • (FK) denota una clave externa

Estas son las tablas (si ayuda me pueden enviar el código SQL para generar ellos, pero no creo que las mesas son en realidad el problema ya que la excepción es en la validación del modelo):

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 

Estas son las entidades (aviso de que estoy incluyendo las claves externas en el modelo pero aparte de eso bastante estándar):

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; } 
} 

Y aquí está el contexto de datos:

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); 
    } 
} 

por último, este es un fragmento de código para hacer que la excepción:

using (var ctx = new DbCtx(@".....")) 
{ 
    Console.WriteLine(ctx.Twos.Count()); 
} 

Respuesta

40

el motivo del error se relaciones mal configuradas en su modelo. Esto no es correcto:

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); 

que debe ser:

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

Debido FK del dependiente debe contener todas las columnas de PK director. También debe eliminar la propiedad de navegación de Three a One.

+1

Genial, gracias - ¡Estaba golpeando mi cabeza contra eso por un tiempo! – kmp

1

Nota para EF5 +: .HasForeignKey ya no se utiliza de EF 5: Lista de métodos disponibles (https://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.configuration.manytomanyassociationmappingconfiguration_methods(v=vs.103).aspx) - MapLeftKey - MapRightKey - totable

Si uno fuera a necesitar muchos a muchos donde uno 'Muchos 'es una entidad con una CompositeKey es:

one.HasKey(t => new { t.TwoId, t.ThreeId }); 
one.HasRequired(t => t.Two) 
    .WithMany(s => s.Ones) 
    .Map(m=>m.MapLeftKey("OneId").MapRIghtKey(new string[]{"TwoId", "ThreeId"})) 
1

Esto también puede ser causada por Code first from Database.

Tenía varias vistas que traje que no tenían un campo clave obvio de acuerdo con las convenciones de Entity Framework. El código generado pone el atributo [Key] en el campo incorrecto. De hecho, no pudo detectar ninguna singularidad, por lo que puso el atributo [Key] en todos los campos.

Pude eliminar todos los atributos clave adicionales para que desapareciera el error.

Cuestiones relacionadas