Есть ли способ сбросить DbContext, не удаляя и не восстанавливая его? - PullRequest
9 голосов
/ 13 апреля 2011

Я недавно провела рефакторинг приложения WPF, чтобы оно больше не включало каждое использование DbContext в предложение using (см. этот вопрос ).Вместо этого мое приложение просто использует один и тот же синглтон DbContext.

Это прекрасно работает, за исключением одной небольшой проблемы.У меня есть процедура, которая восстанавливает базу данных с нуля и вставляет некоторые данные по умолчанию.Эта подпрограмма использует ADO.NET напрямую (не DbContext), поэтому DbContext не знает, что база данных теперь совершенно другая.

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

Ответы [ 2 ]

6 голосов
/ 14 апреля 2011

Мне не удалось придумать метод сброса глобального DbContext. Однако я смог решить свою проблему, внедрив DbContextLocator в любой класс, которому нужен DbContext, вместо передачи самого DbContext.

Моя цель состояла в том, чтобы поддерживать глобальный DbContext, но разрешать его сброс при необходимости (например, после перестройки или импорта базы данных).

Мое решение использует абстрактный базовый класс и конкретный класс.

Базовый класс

using System.Data.Entity;

namespace CommonLibrary.Database
{
    public abstract class DbContextLocator
    {
        private DbContext _dbContext;

        public DbContext Current
        {
            get { return _dbContext; }
        }

        public DbContextLocator()
        {
            _dbContext = GetNew();
        }

        public virtual void Reset()
        {
            _dbContext.Dispose();
            _dbContext = GetNew();
        }

        protected abstract DbContext GetNew();
    }
}

Класс бетона

using System.Data.Entity;
using CommonLibrary.Database;
using ExperimentBase.EntityModels;

namespace MainProject.Models    
{
    public class MainDbContextLocator : DbContextLocator
    {
        public new MainDbContext Current
        {
            get { return (MainDbContext)base.Current; }
        }

        protected override DbContext GetNew()
        {
            return new MainDbContext();
        }
    }
}

Использование

Получить текущий DbContext:

var dbContext = dbContextLocator.Current;

Сброс DbContext:

dbContextLocator.Reset();
//Note: normally followed by code that re-initializes app data

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

Основываясь на отзывах Шимми, я превратил DbContextLocatorBase в универсальный. (Я также сейчас реализую IDisposable.)

Базовый класс

public class DbContextLocator<TContext> : IDisposable
    where TContext : DbContext, new()
{
    private TContext _dbContext;

    public TContext Current
    {
        get { return _dbContext; }
    }

    public DbContextLocator()
    {
        _dbContext = GetNew();
    }

    public virtual void Reset()
    {
        _dbContext.Dispose();
        _dbContext = GetNew();
    }

    protected virtual TContext GetNew()
    {
        return new TContext();
    }

    public void Dispose()
    {
        _dbContext.Dispose();
    }
}

Класс бетона (необязательно, поскольку базовый класс больше не является абстрактным)

public class MainDbContextLocator : DbContextLocator<MainDbContext> { }
5 голосов
/ 13 апреля 2011

Держать ObjectContext открытым в течение всего срока службы приложения - это, как правило, плохая идея.

ObjectContext (или в данном случае DbContext) предназначен для единицы работы.

См. Entity Framework и пул соединений

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...