我使用实体框架4.3.1对SQL Server 2012数据库,我使用的是POCO的方法。我收到以下错误,我想知道如果任何人都可以解释如何解决它:
ModelValidationException
模型生成过程中检测到一个或多个验证错误: \ tSystem.Data.Entity.Edm.EdmAssociationConstraint::在关系约束的依赖和主要角色的属性数必须相同
没有的InnerException
可用于任何进一步的信息。
我不能更改数据库模式,这是一个有点古怪,但在这里它是...
**是主键(注意我有复合主键) (FK)表示外键下面是表(如果有帮助,我可以张贴在SQL生成它们,但我不认为这些表是实际问题的例外是在模型的验证):
一
-
** OneId INT NOT NULL
** TwoId INT NOT NULL(FK)
** ThreeId INT NOT NULL(FK)
名称为nvarchar(50)非空
二
-
** TwoId INT NOT NULL
** ThreeId INT NOT NULL(FK)
名称为nvarchar(50)非空
三
-
** ThreeId NOT NULL
名称为nvarchar(50)非空
下面是实体(请注意,我包括在模型中的外键,但高于pretty的标准等):
公共类三
{
公众诠释ThreeId {获得;组; }
公共字符串名称{;组; }
公共虚拟的ICollection<二>三三两两{获得;私定; }
公共虚拟的ICollection<一>问鼎{获得;私定; }
公共无效AddOne(一一)
{
如果(一个== NULL)
抛出新ArgumentNullException(二);
如果(问鼎== NULL)
问鼎=新的名单,其中,一>();
如果(!Ones.Contains(一个))
Ones.Add(之一);
one.Three =这一点;
}
公共无效AddTwo(二二)
{
如果(二== NULL)
抛出新ArgumentNullException(二);
如果(三三两两== NULL)
三三两两=新名单,其中;二>();
如果(!Twos.Contains(2))
Twos.Add(二);
two.Three =这一点;
}
}
公共类二
{
公众诠释TwoId {获得;组; }
公众诠释ThreeId {获得;组; }
公共字符串名称{;组; }
公共虚拟三三{获得;组; }
公共虚拟的ICollection<一>问鼎{获得;私定; }
公共无效AddOne(一一)
{
如果(一个== NULL)
抛出新ArgumentNullException(二);
如果(问鼎== NULL)
问鼎=新的名单,其中,一>();
如果(!Ones.Contains(一个))
Ones.Add(之一);
one.Two =这一点;
}
}
公共类一
{
公众诠释OneId {获得;组; }
公众诠释TwoId {获得;组; }
公众诠释ThreeId {获得;组; }
公共虚拟两个二{获得;组; }
公共虚拟三三{获得;组; }
}
这里是数据方面:
公共类DbCtx:的DbContext
{
公共DbCtx(字符串的connectionString)
:基地(的connectionString)
{
问鼎=设置<一>();
三三两两=设置<二>();
三分球=设置<三>();
}
公共DbSet<一>问鼎{获得;私定; }
公共DbSet<二>三三两两{获得;私定; }
公共DbSet<三>三分{获得;私定; }
保护覆盖无效OnModelCreating(DbModelBuilder模型构建器)
{
VAR 1 = modelBuilder.Entity<一>();
one.ToTable(1);
one.HasKey(D =>新建
{
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 2 = modelBuilder.Entity<二>();
two.ToTable(二);
two.HasKey(D =>新建
{
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 3 = modelBuilder.Entity<三>();
three.ToTable(三公);
three.HasKey(S => s.ThreeId);
three.Property(P => p.ThreeId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
base.OnModelCreating(模型构建器);
}
}
最后,这是code片段导致异常:
使用(VAR CTX =新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 =>新建{t.TwoId,t.ThreeId});
由于相关的FK必须包含主要PK的所有列。此外,还必须从三
到一
。
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 keyHere 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());
}
解决方案
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
.