Подтвердить что ты не робот

Как исправить: количество свойств в зависимых и основных ролях в ограничении отношений должно быть одинаковым?

Я использую Entity Framework 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());
}
4b9b3361

Ответ 1

Причиной ошибки являются неверно настроенные отношения в вашей модели. Это неверно:

    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.

Ответ 2

Примечание для 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

Если кому-то понадобится много для многих, где одно "много" относится к сущности с композитным ключом:

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

Ответ 3

Это также может быть вызвано Код сначала из базы данных.

У меня было несколько просмотров, которые я привел, у которых не было очевидного ключевого поля в соответствии с соглашениями Entity Framework. Созданный код помещает атрибут [Key] в неправильное поле. Фактически, он не мог обнаружить никакой уникальности, поэтому он помещает атрибут [Key] во все поля.

Мне удалось удалить все дополнительные атрибуты Key, чтобы ошибка исчезла.