C # / EF и шаблон репозитория: куда поместить ObjectContext в решение с несколькими репозиториями? - PullRequest
5 голосов
/ 17 февраля 2011

У меня есть несколько репозиториев в моем приложении. Где я должен поместить ObjectContext? Прямо сейчас у меня есть ссылка типа ObjectContext ctx; в каждом хранилище. Какой самый разумный и безопасный способ сделать это?

Ответы [ 2 ]

10 голосов
/ 17 февраля 2011

Проект с несколькими экземплярами ObjectContext допустим только в том случае, если ваши Repository методы фиксируют транзакцию. В противном случае, возможно, что внешние вызовы для фиксации транзакции не сохранят все, что вы намереваетесь, потому что вы будете хранить ссылки на различные экземпляры ObjectContext.

Если вы хотите ограничить ObjectContext одним экземпляром, то вы можете создать класс RepositoryProvider, который содержит ObjectContext и управляет распространением действий репозитория на фиксации данных. Это может быть лучше всего достигнуто любым, - вставка ссылки ObjectContext в каждый репозиторий или - Подписка событий репозиториев на EventHandler s, которые вызывают соответствующие методы на ObjectContext.

Ниже приведена очень плагинная реализация, которую я использовал:

Интерфейс провайдера репозитория

public interface IRepositoryProvider
{
    IRepository this[Type repositoryType] { get; }
}

Интерфейс хранилища фабрики

Реализация зависит от IEnumerable<IFilteredRepositoryFactory>.

public interface IFilteredRepositoryFactory{
   bool CanCreateRepository(Type repositoryType);
   IRepository CreateRepository(Type repositoryType, ObjectContext context);
}

Итак, реализация выглядит так:

Класс поставщика репозитория

public class RepositoryProvider
{
    public RepositoryProvider(ObjectContext context, IEnumerable<IFilteredRepositoryFactory> repositoryFactories)
    {
        _context = context;
        _repositoryFactories = repositoryFactories;
    }

    private readonly ObjectContext _context;
    private readonly IEnumerable<IFilteredRepositoryFactory> _repositoryFactories;
    private readonly Dictionary<Type, IRepository> _loadedRepositories;

    IRepository this[Type repositoryType]
    {
        get
        {
            if(_loadedRepositories.ContainsKey(repositoryType))
            {
                return _loadedRepositories[repositoryType];
            }
            var repository = GetFactory(repositoryType).CreateRepository(repositoryType, _context);
            _loadedRepositories.Add(repositoryType,repository);
            return repository;
        }
    }

    IFilteredRepositoryFactory GetFactory(Type repositoryType)
    {
        //throws an exception if no repository factory is found
        return _repositoryFactories.First(x => x.CanCreateRepository(repositoryType));
    }
}

Следует отметить, что новая Repository будет создана первой соответствующей фабричной реализацией. Таким образом, если коллекция фабрик содержит несколько фабрик, которые могут создать Repository для данного репозитория Type, будет использован первый объект IFilteredRepositoryFactory в перечисляемом объекте, а любые последующие фабрики будут игнорироваться , Кроме того, если зарегистрированной фабрики нет, будет выдано исключение.

0 голосов
/ 29 июня 2011

Что я обычно делаю, это создаю ObjectContext один раз и сохраняю его в Thread Local Storage (используя NamedThreadDataSlot) и получаю доступ к ObjectContext оттуда. Это гарантирует, что ObjectContext является общим для запроса, который будет обрабатываться одним потоком.

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