EF6 Разделение таблицы и исключение «Зависимое свойство в ReferentialConstraint сопоставлено с созданным хранилищем столбцом. Столбец:« Id ».» - PullRequest
0 голосов
/ 02 мая 2020

В течение некоторого времени я следовал правилу «Коллекции первого класса» из Object Calisthenics в моем дизайне домена. Чтобы избежать создания бесполезной таблицы «Collection», я использую конфигурацию разбиение таблицы из Entity Framework.

Но если по какой-то причине у меня есть класс Parent, который не ' Не имея свойств, кроме его Id и дочерней коллекции, я получаю исключение:

InvalidOperationException: Зависимое свойство в ReferentialConstraint сопоставляется со столбцом, сгенерированным хранилищем. Колонка: 'Id'.

Странно то, что база данных создана правильно, и я могу запросить ее, но сохранение невозможно.

Если я просто добавлю еще одно свойство Parent, проблема исчезает, что еще более странно.

Я сузил его до очень простого теста:

Program.cs

class Program
{
    static void Main(string[] args)
    {
        using (var context = new MyContext(new DropCreateDatabaseAlways<MyContext>()))
        {
            context.Set<Parent>().Find(1);
        }

        using (var context = new MyContext(new CreateDatabaseIfNotExists<MyContext>()))
        {
            context.Set<Parent>().Add(
                new Parent()
                {
                    ChildrenCollection = new ChildrenCollection()
                    {
                        List = new List<Child>() { new Child() }
                    }
                });
            context.SaveChanges(); // Exception thrown here
        }
    }
}

Домен

public class Parent
{
    public int Id { get; set; }
    public virtual ChildrenCollection ChildrenCollection { get; set; }
}

public class ChildrenCollection
{
    public int Id { get; set; }
    public virtual IList<Child> List { get; set; }
}

public class Child
{
    public int Id { get; set; }
}

Контекст

public class MyContext : DbContext
{
    public MyContext(IDatabaseInitializer<MyContext> dbInitializer)
        : base(nameOrConnectionString: GetConnectionString())
    {
        Database.SetInitializer(dbInitializer);
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new ChildrenCollectionConfiguration());
        modelBuilder.Configurations.Add(new ParentConfiguration());

        base.OnModelCreating(modelBuilder);
    }

    private static string GetConnectionString()
    {
        return @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=TestEntityFramework;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;MultipleActiveResultSets=true;";
    }
}

Конфигурация

public class ParentConfiguration : EntityTypeConfiguration<Parent>
{
    public ParentConfiguration()
    {
        HasRequired(x => x.ChildrenCollection)
            .WithRequiredPrincipal();
    }
}

public class ChildrenCollectionConfiguration : EntityTypeConfiguration<ChildrenCollection>
{
    public ChildrenCollectionConfiguration()
    {
        #region Configure Table Splitting

        var parentTable = typeof(Parent).Name;

        ToTable(parentTable);

        HasMany(x => x.List)
            .WithRequired()
            .Map(x =>
            {
                x.MapKey(string.Concat(parentTable, "_Id"));
            });

        #endregion
    }
}

1 Ответ

0 голосов
/ 02 мая 2020

Порядок конфигурации имеет значение, родительская конфигурация должна быть на первом месте.

Поддержание логического порядка конфигурации от Родителя к Дочернему является естественным при настройке непосредственно из класса DbContext, но когда вы отделяете конфигурацию, используя EntityTypeConfiguration<TEntity>, это может быть не так.

Похоже, что это ошибка в Entity Framework для этого конкретного c сценария, поскольку он работает в большинстве случаев.

Чтобы убедиться, что он всегда работает, сначала вызовите конфигурацию для классов выше в иерархии.

public class MyContext : DbContext
{
    ...
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new ParentConfiguration()); // must come first
        modelBuilder.Configurations.Add(new ChildrenCollectionConfiguration()); // comes after

        base.OnModelCreating(modelBuilder);
    }
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...