2012-08-01 33 views
21

我正在使用實體框架4.3.1針對SQL Server 2012數據庫,我正在使用POCO方法。我收到以下錯誤,我想知道如果任何人都可以解釋如何解決它:如何解決:關係約束中的從屬角色和主角色中的屬性數量必須相同?

ModelValidationException模型生成過程中檢測到

一個或多個驗證錯誤: \ tSystem.Data .Entity.Edm.EdmAssociationConstraint::關係約束中的從屬角色和主角色中的屬性數量必須相同。

有任何進一步的信息,沒有InnerException可用。

我不能更改數據庫架構,這是一個有點古怪,但在這裏它是...

  • **是主鍵(注意我有複合主鍵)
  • (FK)表示一個外鍵

下面是表(如果有幫助,我可以張貼的SQL生成他們,但我不認爲表實際上是這個問題的例外是在模型的驗證):

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 

下面是實體(請注意,我在模型中包括外鍵,但比那個漂亮的標準等):

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

,這裏是數據方面:

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

最後,這是一個代碼段,以使異常:

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

回答

40

的原因是錯誤在您的模型中錯誤配置關係。這是不正確的:

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

它應該是:

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

因爲相關的FK必須包含主要PK中的所有列。您還必須從Three刪除導航屬性到One

+1

太好了,謝謝 - 我一直在對着我的頭撞了一會兒! – kmp 2012-08-01 08:24:23

1

注意事項EF5 +: .HasForeignKey已經從EF 5棄用:可用的方法(https://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.configuration.manytomanyassociationmappingconfiguration_methods(v=vs.103).aspx) 列表 - MapLeftKey - MapRightKey - ToTable

如果一個人需要多對多其中一個「多'是一個實體與一個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

這也可以通過Code first from Database引起。

我有幾個視圖,我根據實體框架約定沒有明確的關鍵字段。生成的代碼將[Key]屬性放在錯誤的字段上。事實上,它無法檢測到任何唯一性,因此它將[Key]屬性放在所有字段上。

我能夠刪除所有額外的關鍵屬性,使錯誤消失。

相關問題