34

SQL Server 2012 データベースに対して Entity Framework 4.3.1 を使用しており、POCO アプローチを使用しています。次のエラーが表示されます。誰かがそれを修正する方法を説明できるかどうか疑問に思っています:

モデル検証例外

モデルの生成中に 1 つ以上の検証エラーが検出されました: \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());
}
4

3 に答える 3

50

エラーの理由は、モデルで正しく構成されていない関係です。これは正しくありません:

    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

于 2012-08-01T08:05:25.053 に答える