Как предотвратить доступ к родительской EF единице работы - PullRequest
1 голос
/ 21 апреля 2020

Я понимаю, что это довольно похоже, по крайней мере, в заголовке, на Вложенная единица работы в Entity Framework и Единица работы и EF . Я посмотрел на них и не думаю, что вопросы или ответы на них касаются нашего варианта использования.

У меня есть то, что уже похоже на вонючий код, с которым я пытаюсь работать / улучшать. Сценарий пытается выполнить некоторую реализацию Unit of Work с «основным» UOW верхнего уровня, у которого есть фабричный метод для создания вложенных дочерних объектов UOW. Так что-то вроде

public interface IUnitOfWork
{
    public IFancyEntityDataAccess { get; }

    public IUnitOfWork CreateChildUow();
}

public interface IFancyDataAccess
{
    public void DoSomeRawSqlPreprocessing();

    public FancyEntity ReadFancyEntity(int id);
}

Каждое UOW имеет свою собственную Entity Framework DbContext для выполнения операций доступа к данным. (Я понимаю, что EF уже является чем-то вроде UOW, но мы стараемся не давать нашему бизнес-уровню c прямой доступ к нашему уровню доступа к данным DbContext.) Иногда мы сталкиваемся со случаями использования, когда нам нужно использовать raw SQL запросов к базе данных (конечно, безопасно спрятаны в их собственных методах DAL) - например, массовая вставка, о которой EF медлит sh, или иерархический Oracle запрос, который не переводится с Linq в SQL. Любая из этих необработанных SQL операций может изменить базу данных без выполнения DbContext, поэтому любые кэшированные объекты могут быть признаны недействительными. (Предположим, ради вопроса, что мы не можем эффективно аннулировать кэш для нашей модели предметной области. Изучение способов сделать это возможно, но это довольно запутанно.) Поэтому, чтобы обеспечить свободный sh кэш, у нас есть объект UOW. создайте дочерний элемент UOW, сделайте так, чтобы он в конце концов сделал raw SQL со своим дочерним элементом DbContext, а затем утилизируйте дочерний элемент UOW. Затем мы идем вместе с основным UOW, которое до сих пор не (читай, лучше не было) ничего не сделало с сущностями или DbSet s, затронутыми дочерней операцией UOW raw SQL. Поэтому, когда он загружает свои данные из своего основного DbContext, он получает данные fre sh post-raw- SQL. В конечном итоге это выглядит примерно так:

using (var child = mainUow.CreateChildUow())
{
    child.FancyEntityDataAccess.DoSomeRawSqlPreprocessing();
}

// Provided this is the main UOW's first use of `DbSet<FancyEntity>`, it will get fresh results
var entity = mainUow.FancyEntityDataAccess.ReadFancyEntity(5);

Что мне не нравится в этой настройке - ничто не мешает основному UOW каким-либо образом использовать DbSet<FancyEntity> до того, как дочернее UOW выполнит свою работу. Если основное UOW уже заранее кэшировало FancyEntity, то это уничтожает всю цель дочернего UOW. Это может произойти при использовании основного UOW до дочернего UOW, либо внутри блока using дочернего элемента, либо перед ним.

Я предполагаю, что фундаментальная проблема заключается в том, что у нас нет согласованного контекста из необработанного SQL. Я думаю, что идеальным решением было бы как-то сделать недействительным контекст после необработанного SQL, чтобы все было согласованно, и просто использовать этот один контекст в одном UOW. Для этого можно попробовать аннулировать / отключить кэш Entity Framework .

Но, опять же, за исключением этой возможности, вторичная проблема здесь заключается в том, что как основное, так и дочернее UOW существуют в одной и той же области видимости. Мне бы хотелось, если бы был какой-то способ предотвратить использование основного UOW до потомка - возможно, полностью запретив использование родителя в этом сценарии, вместо использования второго дочернего UOW для выполнения пост- SQL ReadFancyEntity. Несмотря на это, сам факт того, что CreateChildUow вызывается для основного экземпляра UOW и возвращает другой экземпляр UOW , кажется, вызывает эту путаницу, позволяя использовать родителя вне очереди.

Поэтому я предполагаю, что мой вопрос заключается в том, могу ли я как-то работать с таким типом установки UOW для детей и не иметь доступа к основному UOW, который его сгенерировал? Думая, что это может быть что-то вроде полного избавления от основного UOW и просто с фабричным методом CreateUow, но я не совсем уверен, что хочу нажать этот триггер прямо сейчас. Наличие основного UOW полезно в случае основного использования, который не требует такого рода специальных необработанных операций SQL. Просто интересно, если кто-нибудь уже сталкивался / решил это.

...