Ninject кэширует введенный DataContext? Управление жизненным циклом? - PullRequest
5 голосов
/ 23 декабря 2010

У меня была серия очень странных ошибок в моих репозиториях.Строка не найдена или изменена, 1 из 2 обновлений не удалось ... Ничего не имеет смысла.

Как будто мой экземпляр DataContext кэшировался ... Ничего не имело смысла, и я подумывал о карьерном росте.

Затем я заметил, что экземпляр DataContext был передан с использованием внедрения зависимости,используя Ninject (это первый раз, когда я использовал DI ...).Я вырвал инъекцию зависимости, и все пришло в норму.Мгновенно.

Итак, внедрение зависимостей было проблемой, но я до сих пор не знаю, почему.Я предполагаю, что Ninject кэшировал введенный DataContext.

Это правильно?

Редактировать:

Привязка Ninject выглядит следующим образом:

Bind<IPupilBlockService>().To<SqlPupilBlockService>()
   .WithConstructorArgument("db", new dbDataContext());

Ответы [ 3 ]

14 голосов
/ 23 декабря 2010

Для любого объекта, срок жизни которого должен явно управляться (например, объекты, которые реализуют IDisposable) или имеет значение для пользователя, старайтесь не внедрять их, а внедряйте фабрику, которая вместо этого позволяет создавать такие объекты. Определите этот интерфейс, например:

public interface IDbDataContextFactory
{
    dbDataContext CreateNew();
}

И используйте его следующим образом:

public class SqlPupilBlockService
{
    private IDbDataContextFactory contextFactory;

    public SqlPupilBlockService(
        IDbDataContextFactory contextFactory)
    {
        this.contextFactory = contextFactory;
    }

    public void DoSomeOperation()
    {
        using (var db = this.contextFactory.CreateNew())
        {
           // use the dbDataContext here.
        }
    }
}

Реализация была бы очень простой, как это:

public class DbDataContextFactory : IDbDataContextFactory
{
    public dbDataContext CreateNew()
    {
        return new dbDataContext();
    }
}

И регистрация идет так:

Bind<IDbDataContextFactory>().To<DbDataContextFactory>();

Использование фабрики очень четко указывает, кто является владельцем созданного объекта, а кто должен контролировать его время жизни. Это делает ваш код более читабельным и следует принципу наименьшего удивления .

UPDATE

Прошло более года с тех пор, как я отправил этот ответ. Вместо того чтобы использовать фабрики, я теперь часто внедряю сам контекст данных и регистрирую его для каждого (веб) запроса. Тем не мение; Как всегда, может потребоваться изменение в том, как вам нужно разрабатывать ваше приложение: это зависит. Пожалуйста, посмотрите на этот ответ .

3 голосов
/ 29 июля 2012

@ Стивен дал отличное объяснение, но на самом деле, Ninject уже дает вам возможность указать, что экземпляр должен генерироваться для запроса: InRequestScope .

Bind<IPupilBlockService>()
   .To<SqlPupilBlockService>()
   .InRequestScope()
   .WithConstructorArgument("db", new dbDataContext());
1 голос
/ 23 декабря 2010

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

(я не слишком знаком с ninject, но данная временная область является значением по умолчанию, я ожидаю, что где-то в коде вашего приложения DataContext явно определен как имеющий непереходную область)

...