Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Введенная зависимость DbContext пуста после заполнения DbContext, созданного с помощью new (EF7, ASP.NET 5, vnext)

Автор вопроса: RyanОтветов: 1

Я относительно новичок в EF7 и слышал, что внедрение зависимостей DbContexts в конструктор контроллера - хороший способ получить DbContext для использования в заданных методах действия. Однако есть много ситуаций, когда внедрение зависимостей невозможно (например, доступ к базе данных в обычных классах), и необходимо использовать шаблон using(VectorDbContext dbContext...).

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

Вот код, который добавляет сущности в DbContext, для тестирования я вызываю это в Startup.cs:

using (ExampleDbContext dbContext= new ExampleDbContext()) {
    dbContext.Things.Add(
        new Thing() {
            Stuff= "something"
        });

    dbContext.SaveChanges();
}

Вот код доступа в контроллере:

public class ExampleController : Controller {
    public ExampleController(ExampleDbContext exampleDbContext) {
        this.ExampleDbContext= exampleDbContext;
    }

    public ExampleDbContext ExampleDbContext { get; set; }

    public async Task<IActionResult> ExampleAction() {

        // new DbContext:
        using(ExampleDbContext dbContext = new ExampleDbContext ()) {
            var List1 = (await dbContext.Things
                .AsNoTracking()
                .ToListAsync());
        }

        // Injected DbContext:
        var List2 = (await this.ExampleDbContext.Things
            .AsNoTracking()
            .ToListAsync());
    }
}

При пошаговом прохождении List1 содержит ожидаемый один элемент, но List2 всегда пуст!

Что я делаю неправильно? Похоже, что DbContexts каким-то образом не синхронизируются, как инъекция зависимостей создает DbContext / откуда он?

РЕДАКТИРОВАТЬ: Я только что провел дополнительное тестирование и подтвердил, что любые объекты, добавленные в DbContext, созданные с помощью new, видны только в new, а объекты, добавленные в Injected DbContext, видны только внутри Injected DbContext, что заставляет меня поверить, что они подключаются к разным базам данных, но я не могу подтвердить.

  • Что касается того, где происходит инъекция DbContext: я реализовал SimpleInjector, чтобы сделать это за меня, следуя нашему уважаемому S.O. член Стивен и его блог о том, как это реализовать. Я нашел его подход очень полезным, может быть, вы сможете решить, как решить вашу проблему с помощью его пошагового руководства! Allmighty 29.01.2015
  • В настоящее время я использую MVC6, встроенный в Dependency Injector, по-видимому, он создает объекты для каждой области запроса , как описано здесь, и удаляет их впоследствии. Понятия не имею, почему один и тот же DbContext представляет два разных представления данных. Спасибо за ссылку в блоге, я мог бы реализовать это для более точного контроля. Ryan 29.01.2015
  • @Ryan - Это не тот же DbContext. Вы создали новый. Это два отдельных DbContexts, поэтому, конечно, они содержат разные наборы данных в своих внутренних кэшах. Понятия не имею, зачем вы создаете новый экземпляр .. Erik Funkenbusch 29.01.2015
  • @Ryan - также вы ошибаетесь на 100% (ну да ладно, ошибаетесь на 99,9%) в том, что во многих ситуациях внедрение зависимостей невозможно. Вы просто не понимаете, как внедрять зависимости и как правильно ее использовать. Erik Funkenbusch 29.01.2015
  • @ErikFunkenbusch Извините, это два разных экземпляра DbContext, однако они все равно должны предоставлять доступ к одной и той же резервной базе данных и, следовательно, содержать одни и те же данные при создании, учитывая, что данные были добавлены до создания любого из них. Кеш тут не причем? Кроме того, мне нужен доступ к DbContext в настраиваемом IRouteConstraint, который я создаю явно в ConfigureServices при запуске. Учитывая, что EF не может (по умолчанию) внедрять зависимости в методы, а только в конструкторы, я не могу использовать поставщика внедрения зависимостей для получения. Ryan 29.01.2015
  • @ErikFunkenbusch Я согласен с вами насчет двух отдельных DbContext, но разве каждый из них не должен выходить за пределы своего внутреннего кеша и напрямую запрашивать базу данных и, следовательно, возвращать одни и те же данные? Sergey Kolodiy 29.01.2015

entity-frameworkentity-framework-coredbcontext

Ответы

Ответ 1 · рейтинг 2 · Sergey Kolodiy

Возможно, я ошибаюсь, но я предполагаю, что когда вы создаете новый экземпляр DbContext в коде, вы используете конструктор без параметров, который устанавливает для базовой строки подключения некоторое значение по умолчанию. Однако внедренный DI DbContext может быть разрешен с помощью другого конструктора с другой строкой подключения, переданной явно.

Это пример конфигурации Unity, в которой явно указан параметр конструктора:

<register type="DbContext, [assembly-name]" mapTo="DbContext, [assembly-name]">
<constructor>
    <param name="nameOrConnectionString" value="Test"/>
</constructor>
</register>

Поэтому я бы проверил конфигурацию вашего контейнера.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы