Перезагрузка свойств навигации в EF6

Я прочитал много вопросов о stackoverflow относительно перезагрузки свойства навигации с помощью Context.Entry(entity).Collection(p=>p.Property).Load(), но в моем случае он не дает мне обновленных значений из базы данных.

Для параметров LazyLoading и ProxyCreation установлены значения по умолчанию, которые, как я читал, по умолчанию включены.

У меня есть объект Entity Test, который я извлек из базы данных, используя активную загрузку со всеми связанными свойствами, используя метод ниже:

var test = Repository.GetById(testId, null, true, new Expression<Func<Test,object>>[] {
    bt=>bt.Baselining,
    ct=>ct.Baselining.BaselineTestCase,
    dt=>dt.Baselining.BaselineTestCase.Baseline,
    ft=>ft.Baselining.Transaction,
    gt=>gt.Baselining.Transaction>Select(x=>x.Fields)
}); 

public virtual T GetById<T>(int id, Func<T,bool> where = null, bool trackChanges = false, params Expression<Func<T,object>>[] includeProps) 
{
    T item = null;
    IQuerable<T> dbQuery = Context.Set<T>();

    if (includeProps != null)
        foreach(Expression<Func<T,object>> navProp in includeProps)
            dbQuery = dbQuery.Include<T,object>(navProp);

    if (where == null)
    {    
        if (!trackChanges) item = dbQuery.AsNoTracking().FirstOrDefault(t=>t.Id == id);
        else item = dbQuery.FirstOrDefault(t=>t.Id == id);
    }
    else
    {
        if (!trackChanges) item = dbQuery.AsNoTracking().Where(where).FirstOrDefault(t=>t.Id == id);
        else item = dbQuery.Where(where).FirstOrDefault(t=>t.Id == id);
    }
    return item;
}

Я пытаюсь перезагрузить Baselining.Transaction.Fields, используя

Repository.Reload(test);
Repository.Reload(test.Baselining.BaselineTestCase);
Repository.Reload(test.Baselining.BaselineTestCase.Baseline);
Repository.ReloadNavigationProperties(test.Baselining, x=>x.Transaction);
foreach(var tq in test.Baselining.Transaction)
    Repository.ReloadNavigationProperties(tq, x=>x.Fields);

Методы репозитория выглядят примерно так:

public virtual void ReloadNavigationProperties(TEntity,TElement>(TEntity entity, Expression<Func<TEntity,ICollection<TElement>>> navProp) where TEntity : class where TElement : class
{
    Context.Entry(entity).Collection(navProp).Load();
}

public virtual T Reload<T>(T entity) where T : class {
    Context.Entry(entity).Reload();
    return entity;
}

Я отладил приведенное выше выполнение ReloadNavigationProperties с помощью SQL Profiler, и он действительно обращается к базе данных и также генерирует запрос SQL с соединениями, но мой объект не обновляется даже после перезагрузки.

После того, как я не смог перезагрузить свойства навигации с помощью вышеуказанного метода, я пришел к этому тривиальному подходу, который работает...

foreach(var tq in test.Baselining.Transaction)
    foreach(var tqfs in tq.Fields) 
        Repository.Reload(tqfs);

Потому что у меня есть около 100 полей TransactionQueryField для каждого TransactionQuery, и этот вложенный foreach 100 раз перезагружает каждое поле, и это очень-очень медленно, и оно должно быть медленным...

Вот сущности

public class Test 
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int id {get;set;}
    public virtual Baselining Baselining {get;set;}
    public virtual ICollection<TestExecutionResult> TestCaseResults {get;set;} = new List<TestExecutionResult>();
}

public class Baselining 
{
    public Baselining() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int id {get;set;}
    public DateTime BaseliningDate {get;set;}
    public virtual BaselineTestCase BaselineTestCase {get;set;}
    public virtual ICollection<TransactionQuery> Transaction {get;set;} = new List<TransactionQuery>();
}

public class BaselineTestCase 
{
    public BaselineTestCase() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int id {get;set;}
    public virtual Baseline Baseline {get;set;}
    public virtual ICollection<Baselining> Baselinings {get;set;} = new List<Baselining>();
    public Baselining LastBaselining {
        get {return Baselinings.OrderBy(x=>x.BaseliningDate).LastOrDefault(); }
    }
}

public class TransactionQuery : TransactionItem 
{
    public TransactionQuery() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public override int id {get;set;}
    public virtual Baselining Baselining {get;set;}
    public virtual ICollection<TransactionQueryField> Transaction {get;set;} = new List<TransactionQueryField>();
}

public class TransactionQueryField : TransactionItem 
{
    public TransactionQueryField() {}
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public override int id {get;set;}
    public bool Compare {get;set;}
    public bool Critical {get;set;}
}

public abstract class TransactionItem : BaseEntity<int> {
    public string TestResultCode {get;set;}
}

public abstract class BaseEntity<T> {
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public virtual T Id {get;set;}
}

Я хочу понять, почему активная загрузка с помощью свойств навигации не загружает обновленные данные. Потому что, насколько я понимаю, если я хочу что-то загрузить, он должен совершить обратный путь к базе данных и получить обновленные данные. Но даже нетерпеливая загрузка с перезагрузкой не дает мне обновленных значений.

Извините, если я не объяснил это должным образом, хотя я буду признателен за любую помощь в отношении того, как быстрее загружать мои поля, может быть с одним единственным обходом базы данных.

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

Ответы 1

Это всего лишь гипотеза, но я думаю, что причина, по которой ваши навигационные свойства не перезагружаются, — это отслеживаемые объекты. Я уже сталкивался с чем-то подобным, и о методе Loadдокумент говорит:

Loads the collection of entities from the database. Note that entities that already exist in the context are not overwritten with values from the database.

Когда вы вызываете GetById, вы устанавливаете для параметра trackChanges значение true. С этого момента все нетерпеливо загруженные объекты отслеживаются. Как я уже сказал, я не уверен, что это проблема, но вы можете попробовать установить состояние всех отслеживаемых объектов на EntityState.Detached.

Я читал это, но дело в том, что если я не отслеживаю изменения, то не смогу внедрить Entity Hooks, которые я настроил во время OnSave и OnLoad. Поэтому я должен отслеживать изменения в true. Хотя я пробовал Object context.Refresh, и он работает, но мне очень интересно узнать, как правильно справиться с такой ситуацией со свойствами навигации.

Arsalan Khan 24.01.2019 18:14

Я никогда не использовал пакет EntityHooks, но документ довольно ясно описывает метод Load, и я не могу придумать других способов подняться над ситуацией, кроме как играть с EntityState или свойствами на DbCollectionEntry.

Marco Luzzara 24.01.2019 19:10

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