EF Core: отображение навигационного свойства инкапсулированной коллекции с помощью дополнительного свойства / поля навигационного свойства (частное вспомогательное поле) - PullRequest
0 голосов
/ 05 мая 2019

Резюме


В Entity Framework Core [Code-First] возможно ли отобразить навигационное свойство через частное (или даже публичное) вспомогательное поле этого навигационного свойства? По сути, вместо сопоставления это как:

modelBuilder.Entity<MyEntity>().HasMany(e => e.NavProperty)...

Можем ли мы отобразить это как (по сути, игнорируя Reflection или жестко закодированные строки для краткости):

modelBuilder.Entity<MyEntity>().HasMany(e => e.NavProperty._Data)...

Если NavProperty рассматривается как навигационное свойство и обрабатывать отношения (т. Е. Внешний ключ)?

Кажется, я не могу понять конфигурацию отображения Fluent API, необходимую для достижения такого рода результата. Кажется, я вспомнил, как делал это раньше в EF 6, но, к сожалению, у меня больше нет исходного кода для этого проекта.


Detail


Более полный пример (C #, .NET Standard 2.2., Entity Framework Core 2.2 [Code-First]):

public class Customer
{
    public int CustomerID { get; set; }
    public string Name { get; set; }

    // ...

    public OrderCollection Orders { get; set; }

    public Customer()
    {
    }
}

public class Order
{
    public int OrderID { get; set; }
    public string OrderNo { get; set; }
    public bool Shipped { get; set; }

    // ...

    public Customer Customer { get; set; }

    public Order()
    {
    }
}

public class OrderCollection : IReadOnlyCollection<Order>
{
    private HashSet<Order> orders = new HashSet<Order>();

    public OrderCollection()
    {
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.orders.GetEnumerator();
    }

    public void Add(Order order)
    {
        this.orders.Add(order);
        // ... Other logic here
    }

    public bool Contains(Order order)
    {
        // ... Other logic here
        return this.orders.Contains(order);
    }
}

// The DbContext Class...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    //... Other models setup / plumbing completed
    // How do we map the sub property / field??
    modelBuilder.Entity<Customer>().HasMany(customer => customer.Orders).WithOne(order => order.Customer);
}

Пример несколько надуманный, но довольно простой, однако, только для быстрого ознакомления:

По сути, OrderCollection - это оболочка для частного поля orders HashSet, благодаря которому мы можем инкапсулировать реальные данные из мутаций и вместо этого демонстрировать поведение, которое нам нужно, через интерфейс (-ы), который нам нужен. Это также позволяет обрабатывать события домена и / или другие проблемы в наиболее подходящее время, когда вызывающий абонент / владелец не знает деталей или не должен дублировать логику во всей модели домена (т. Е. Выставление счетов также будет иметь коллекцию заказов, как и качество Контроль и т. Д.). Это также предотвращает утечку зависимостей и сквозных проблем в модель основного домена.


Мозговой


Вот некоторые идеи, которые у меня были для решения проблемы:

1) Имейте OrderCollection наследование от чего-то вроде HashSet<T>, ReadOnlyCollection<T> и т. Д. И просто переопределяйте методы, которые я не хочу раскрывать. В лучшем случае это кажется хакерским и хрупким (т. Е. Мы нарушаем практику «композиция благосклонности над наследством» из-за жуткой магии вуду).

2) Просто отбросьте идею «Коллекции» и поместите вспомогательное поле и всю логику для элемента в объектную модель, что является нарушением DRY (другие модели будут использовать API такого же типа для свойства Orders ) и SRP, потому что теперь мой Customer объект знает, как (то есть детали реализации того, как) обрабатывать добавление Order к себе. Это плохой дизайн.

3) Обрабатывать навигационное свойство вручную через пользовательские SQL / репозитории / геттеры и сеттеры / и т. Д.? Похоже, EF должен делать все это под капотом, и это будет «изобретать велосипед».

Я пытался использовать ValueConverters, но, похоже, они предназначены для обработки нюансов / эзотерических проблем с типами базы данных и типами .NET CLR, которые маршалируются взад и вперед. Возможно, это - лучшее решение, но для корректной работы ему нужен конкретный тип конструкции ValueConverter?

Любая помощь или понимание приветствуется! Спасибо!

...