C#/ EF和存储库模式:将ObjectContext放在具有多个存储库的解决方案中的位置?

Ols*_*sen 6 c# entity-framework repository repository-pattern objectcontext

我的应用程序中有多个存储库.我应该把ObjectContext放在哪里?现在,我ObjectContext ctx;在每个存储库中都有一个引用.什么是最聪明,最安全的方法?

sma*_*man 10

ObjectContext只有在Repository方法提交事务时,才能接受具有多个实例的设计.否则,提交事务的外部调用可能无法保留您想要的所有内容,因为您将保留对该实例的不同实例的引用ObjectContext.

如果要将数据限制ObjectContext为单个实例,则可以构建一个RepositoryProvider包含该实例的类ObjectContext,并管理存储库操作到数据提交的传播.这可以通过以下任一方式实现: - 将ObjectContext引用注入每个存储库,或者 - 将存储库的事件订阅到EventHandler调用适当方法的s ObjectContext.

以下是我使用的高度可插拔的实现:

存储库提供程序接口

public interface IRepositoryProvider
{
    IRepository this[Type repositoryType] { get; }
}
Run Code Online (Sandbox Code Playgroud)

存储库工厂接口

实现依赖于IEnumerable<IFilteredRepositoryFactory>.

public interface IFilteredRepositoryFactory{
   bool CanCreateRepository(Type repositoryType);
   IRepository CreateRepository(Type repositoryType, ObjectContext context);
}
Run Code Online (Sandbox Code Playgroud)

所以,实现看起来像:

存储库提供程序类

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

应该注意的Repository是,第一个匹配的工厂实现将创建一个新的.因此,如果工厂集合包含可以Repository为给定存储库创建的多个工厂,则将使用可枚举中Type的第一个IFilteredRepositoryFactory对象,并且将忽略任何后续工厂.另外,如果没有注册工厂,则会抛出异常.