Общий класс C# Entity Framework → перезагрузить все дочерние сущности

В настоящее время у меня есть база данных иерархии отношений «один ко многим» tblProjects-> tblLines-> tblGroups-> tblStations и т. д. И модель Entity framework 6.

Все эти классы структуры сущностей реализуют базовый класс tblBase:

  public abstract class TblBase : INotifyPropertyChanged
{
    private int _id;
    public int ID
    {
        get
        {
            return _id;
        }
        set
        {
            _id = value;
            NotifyPropertyChanged();
        }
    }

    private Nullable<int> _coid;
    public Nullable<int> COID
    {
        get
        {
            NotifyPropertyChanged();
            return _coid;
        }
        set
        {
            _coid = value;
            NotifyPropertyChanged();
        }
    }

    private string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
            NotifyPropertyChanged();
        }
    }

У меня есть древовидное представление, которое позволяет мне выбрать любой узел в качестве родительского типа, и в настоящее время у меня есть метод для каждого типа, который позволяет мне перезагружать все дочерние объекты.

Я хотел бы увидеть, как это можно сделать универсальным:

      private async static Task<bool> RefreshLinesAsync(LocalUser ThisUser, ProjectEntities DBContext, object Entity)
    {
        List<object> NonExistingNodes = new List<object>();
        var bContinue = false;
        var PassedEntity = Entity as TblBase;

        //Scan through all DB child entities and reload their DB values
       foreach (var SubEntity in DBContext.tblLines.Where(x => x.ProjectID == PassedEntity.ID).ToList())
        {
            await DBContext.Entry(SubEntity).ReloadAsync().ContinueWith(x =>
            {
                if (!x.IsFaulted)
                {
                    if ((SubEntity.COID.GetValueOrDefault() != 0) && (SubEntity.COID.GetValueOrDefault() != ThisUser.ID))
                        NotifyCOIDConflict(SubEntity, new CheckedOutArgs()
                        {
                            ConflictCOID = SubEntity.COID.GetValueOrDefault()
                        });
                    bContinue = true; 
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());
            if (bContinue)
                //Continue to child entities method
                await RefreshGroupsAsync(ThisUser, DBContext, SubEntity);
        }
        return true;
    }

    private async static Task<bool> RefreshGroupsAsync(LocalUser ThisUser, ProjectEntities DBContext, object Entity)
    {
        List<object> NonExistingNodes = new List<object>();

        var bContinue = false;
        var PassedEntity = Entity as TblBase;

        foreach (var SubEntity in DBContext.tblGroups.Where(x => x.LineID == PassedEntity.ID).ToList())
        {
            await DBContext.Entry(SubEntity).ReloadAsync().ContinueWith(x =>
            {
                if (!x.IsFaulted)
                {
                    if ((SubEntity.COID.GetValueOrDefault() != 0) && (SubEntity.COID.GetValueOrDefault() != ThisUser.ID))
                        NotifyCOIDConflict(SubEntity, new CheckedOutArgs()
                        {
                            ConflictCOID = SubEntity.COID.GetValueOrDefault()
                        });
                    bContinue = true;
                }
            }, TaskScheduler.FromCurrentSynchronizationContext());
            if (bContinue)
                await RefreshStationsAsync(ThisUser,DBContext, SubEntity);
        }
        return true;
    }

Единственный метод, который я считаю полезным, - это Set (), хотя он не предоставляет метод Where (), что очень важно, поскольку я не хочу получать всю таблицу.

В dbcontext есть метод Set <TEntity> (), который имеет функцию Where (). Вы можете использовать его со своим базовым типом: DBContext.Set<TblBase>().Where(...).

Seididieci 29.03.2018 09:45

@Seididieci Я пробовал это, у меня есть исключение, что моя tblBase не является частью моей модели

PigSpider 29.03.2018 09:48

Извините, я не заметил, что ваш базовый класс абстрактный ... Как насчет того, чтобы сделать вашу функцию универсальной как private async static Task<bool> RefreshLinesAsync<TEntity>(LocalUser ThisUser, ProjectEntities DBContext, TEntity Entity)?

Seididieci 29.03.2018 09:51

@Seididieci Я мог бы попробовать это, не могли бы вы примерно показать мне, как этот метод будет выглядеть?

PigSpider 29.03.2018 09:57
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
83
1

Ответы 1

Вы можете сделать свои функции универсальными. Возможно, им понравится этот:

private async static Task<bool> RefreshLinesAsync<TEntity>(LocalUser ThisUser, ProjectEntities DBContext, TEntity Entity) where TEntity : TblBase
{
    List<TEntity> NonExistingNodes = new List<TEntity>();
    var bContinue = false;
    var PassedEntity = Entity as TblBase;

    foreach (var SubEntity in DBContext.Set<TEntity>().Where(x => (x as TblBase).ProjectID == PassedEntity.ID).ToList()) {
       //Your other code here...
    }
}

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

Обновлено:

Я забыл упомянуть, что вам нужно преобразовать SubEntity как TblBase внутри цикла foreach, чтобы использовать его ...

РЕДАКТИРОВАТЬ (в ответ на комментарии):

Если вам нужно получить все подклассы TblBase от вашей сущности, вы не сможете сделать свою функцию такой универсальной, если будете хранить их в отдельных таблицах: это станет труднодоступным, когда вам нужно будет добавить больше подклассов.

Я предлагаю вам использовать одну таблицу через Table Per Hierarchy (см. Статью это в MSDN), изменяя TblBase с абстрактного на конкретный класс, тогда вы можете получить их все следующим образом:

 var allSubClassEntities = DBContext.Set<TblBase>();

Я реализовал это, но теперь проблема в том, что моя SubEntity имеет тот же тип, что и моя Entity, и мне нужно, чтобы она принимала тип дочерних сущностей.

PigSpider 29.03.2018 10:46

Кроме того, выражения позволяют мне получить доступ только к свойствам tblBase. ProjectID - это свойство навигации моих таблиц tblLines. Мне нужно как-то указать свойство навигации.

PigSpider 29.03.2018 11:03

Другие вопросы по теме