Составной внешний ключ EntityFramework с наследованием - PullRequest
1 голос
/ 10 июля 2020

У меня есть проект Entity Framework, в котором есть такие модели и конфигурации.

public class Context : DbContext
{
    public DbSet<Field> Fields { get; set; }

    public DbSet<Table> Tables { get; set; }

    public DbSet<Column> Columns { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Configurations.Add(new FieldConfiguration());
        modelBuilder.Configurations.Add(new TableConfiguration());
        modelBuilder.Configurations.Add(new ColumnConfiguration());
    }
}

public class Field
{
    public Guid Guid { get; set; }

    public Guid CompanyGuid { get; set; }
}

public class Column : Field
{
    public Guid TableGuid { get; set; }

    public Table Table { get; set; }
}

public class Table : Field
{
    public List<Column> Columns { get; set; }
}

public class FieldConfiguration : EntityTypeConfiguration<Field>
{
    public FieldConfiguration()
    {
        Map(t =>
        {
            t.ToTable("Field");
        });
        HasKey(p => new { p.Guid, p.CompanyGuid });
        Property(p => p.Guid).HasColumnName("Guid").IsRequired();
        Property(p => p.CompanyGuid).HasColumnName("CompanyGuid").IsRequired();

    }
}

public class ColumnConfiguration : EntityTypeConfiguration<Column>
{
    public ColumnConfiguration()
    {
        Map(t =>
        {
            t.ToTable("Column");
        });
        HasKey(p => new { p.Guid, p.CompanyGuid });
        Property(p => p.Guid).HasColumnName("Guid").IsRequired();
        Property(p => p.CompanyGuid).HasColumnName("CompanyGuid").IsRequired();
    }
}

public class TableConfiguration : EntityTypeConfiguration<Table>
{
    public TableConfiguration()
    {
        Map(t =>
        {
            t.ToTable("Table");
        });
        HasKey(p => new { p.Guid, p.CompanyGuid });
        Property(p => p.Guid).HasColumnName("Guid").IsRequired();
        Property(p => p.CompanyGuid).HasColumnName("CompanyGuid").IsRequired();
        HasMany(t => t.Columns).WithRequired(t => t.Table).HasForeignKey(t => new { t.TableGuid, t.CompanyGuid }).WillCascadeOnDelete(true);
    }
}

Затем я пытаюсь создать миграцию и получаю такую ​​ошибку

Внешний ключевой компонент CompanyGuid не является объявленным свойством типа Column. Убедитесь, что оно не было явно исключено из модели и является допустимым примитивным свойством.

Что случилось? И как исправить?

1 Ответ

0 голосов
/ 11 июля 2020

Здесь источник проблемы - Field объект. Он используется как таблица базы данных и одновременно используется как базовый класс для других сущностей таблицы. EF не позволяет свойству, которое используется в ограничении внешнего ключа, находиться в нескольких таблицах с наследованием, как в этом случае свойство CompanyGuid является столбцом как Field, так и его производных Column сущностей.

Чтобы преодолеть это ограничение EF, я могу предложить вам два решения:

  1. Первый вариант, создать полностью отдельный базовый класс и унаследовать все 3 объекта от этого базового класса:
    public abstract class EntityBase
    {
        public Guid Guid { get; set; }

        public Guid CompanyGuid { get; set; }
    }

    public class Field : EntityBase
    {
    }

    public class Column : EntityBase
    {
        public Guid TableGuid { get; set; }

        public Table Table { get; set; }
    }

    public class Table : EntityBase
    {
        public List<Column> Columns { get; set; }
    }
Второй вариант: удалить Field наследование и добавить его поля к объектам Table и Column, как показано ниже:
    public class Field
    {
        public Guid Guid { get; set; }

        public Guid CompanyGuid { get; set; }
    }

    public class Column
    {
        public Guid Guid { get; set; }

        public Guid CompanyGuid { get; set; }

        public Guid TableGuid { get; set; }

        public Table Table { get; set; }
    }

    public class Table
    {
        public Guid Guid { get; set; }

        public Guid CompanyGuid { get; set; }

        public List<Column> Columns { get; set; }
    }
...