2012-08-01 3 views
21

Sto utilizzando Entity Framework 4.3.1 su un database SQL Server 2012 e sto utilizzando l'approccio POCO. Sto ottenendo il seguente errore e mi chiedo se qualcuno può spiegare come risolvere il problema:Come risolvere: il numero di proprietà nei ruoli dipendenti e principali in un vincolo di relazione deve essere identico?

ModelValidationException sono stati rilevati

uno o più errori di convalida durante la generazione del modello: \ tSystem.Data .Entity.Edm.EdmAssociationConstraint:: il numero di proprietà nei ruoli dipendenti e principali in un vincolo di relazione deve essere identico.

Non c'è InnerException a disposizione per ogni ulteriore informazione.

non posso cambiare lo schema del database ed è un po 'strano, ma qui è ...

  • ** sono la chiave primaria (notare che ho le chiavi primarie composite)
  • (FK) indica una chiave esterna

Qui ci sono i tavoli (se aiuta posso pubblicare il codice SQL per generarli, ma non credo che i tavoli sono in realtà il problema come l'eccezione è la validazione del modello):

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 

Qui ci sono le entità (si noti che io includo le chiavi esterne nel modello ma a parte questo abbastanza 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; } 
} 

e qui è il contesto dati:

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

Infine, questo è uno snippet di codice per causare l'eccezione:

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

risposta

40

Il motivo dell'errore è relazioni configurate in modo errato nel modello. Questo non è corretto:

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

dovrebbe essere:

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

A causa del dipendente FK deve contenere tutte le colonne di PK principale. È inoltre necessario rimuovere la proprietà di navigazione da Three a One.

+1

Grande, grazie - stavo sbattendo la testa contro quello per un po '! – kmp

1

Nota per EF5 +: .HasForeignKey è stato sconsigliato da EF 5: Elenco dei metodi disponibili (https://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.configuration.manytomanyassociationmappingconfiguration_methods(v=vs.103).aspx) - MapLeftKey - MapRightKey - ToTable

Se si dovesse avere bisogno di molti a molti in cui si 'Molti 'verso un soggetto con un CompositeKey è:

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

Ciò può essere causato anche da Code first from Database.

Ho avuto diversi punti di vista che ho inserito che non avevano un campo chiave ovvio secondo le convenzioni di Entity Framework. Il codice generato inserisce l'attributo [Key] nel campo sbagliato. Di fatto, non è stato in grado di rilevare alcuna univocità, pertanto ha inserito l'attributo [Key] in tutti i campi.

Sono riuscito a rimuovere tutti gli attributi chiave aggiuntivi per far scomparire l'errore.

Problemi correlati