如何修复:关系约束中的从属角色和主要角色中的属性数必须相同?

我正在使用entity framework4.3.1对SQL Server 2012数据库,我正在使用POCO方法。 我收到以下错误,我想知道是否有人可以解释如何解决它:

ModelValidationException

在模型生成期间检测到一个或多个validation错误:\ tSystem.Data.Entity.Edm.EdmAssociationConstraint ::关系约束中的从属角色和主要角色中的属性数必须相同。

没有InnerException可用于任何进一步的信息。

我无法更改数据库架构,这有点奇怪,但这里是……

  • **是主键(注意我有复合主键)
  • (FK)表示外键

以下是表格(如果它有助于我发布SQL以生成它们,但我不认为这些表实际上是问题,因为例外是在模型的validation中):

 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 Twos { get; private set; } public virtual ICollection Ones { get; private set; } public void AddOne(One one) { if (one == null) throw new ArgumentNullException("two"); if (Ones == null) Ones = new List(); 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(); 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 Ones { get; private set; } public void AddOne(One one) { if (one == null) throw new ArgumentNullException("two"); if (Ones == null) Ones = new List(); 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(); Twos = Set(); Threes = Set(); } public DbSet Ones { get; private set; } public DbSet Twos { get; private set; } public DbSet Threes { get; private set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { var one = modelBuilder.Entity(); 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.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.ToTable("Three"); three.HasKey(s => s.ThreeId); three.Property(p => p.ThreeId) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); base.OnModelCreating(modelBuilder); } } 

最后,这是导致exception的代码片段:

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

错误的原因是模型中的关系配置不正确。 这不正确:

  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

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

如果一个人需要多对多,其中一个’Many’是一个具有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"})) 

这也可能是由数据库中的代码首先引起的。

根据entity framework惯例,我提到了几个没有明显关键字段的视图。 生成的代码将[Key]属性放在错误的字段上。 实际上,它无法检测到任何唯一性,因此它将[Key]属性放在所有字段上。

我能够删除所有额外的Key属性以使错误消失。