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

C#/EF和存储库模式:在具有多个存储库的解决方案中,将ObjectContext放在何处?,c#,entity-framework,repository,repository-pattern,objectcontext,C#,Entity Framework,Repository,Repository Pattern,Objectcontext,我的应用程序中有多个存储库。我应该将ObjectContext放在哪里?现在,我有一个参考,比如ObjectContext-ctx在每个存储库中。最聪明和最安全的方法是什么?只有当您的存储库方法提交事务时,才可以接受具有多个ObjectContext实例的设计。否则,提交事务的外部调用可能不会持久化您想要的一切,因为您将持有对ObjectContext的不同实例的引用 如果要将ObjectContext限制为单个实例,则可以构建一个RepositoryProvider类,该类包含ObjectCo

我的应用程序中有多个存储库。我应该将ObjectContext放在哪里?现在,我有一个参考,比如
ObjectContext-ctx在每个存储库中。最聪明和最安全的方法是什么?

只有当您的
存储库
方法提交事务时,才可以接受具有多个
ObjectContext
实例的设计。否则,提交事务的外部调用可能不会持久化您想要的一切,因为您将持有对
ObjectContext
的不同实例的引用

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

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

存储库提供程序接口 存储库工厂接口 该实现依赖于
IEnumerable

因此,实现如下所示:

存储库提供程序类
公共类RepositoryProvider
{
公共RepositoryProvider(ObjectContext上下文,IEnumerable RepositoryFactorys)
{
_上下文=上下文;
_RepositoryFactorys=RepositoryFactorys;
}
私有只读ObjectContext\u上下文;
私有只读IEnumerable\u存储工厂;
私人只读词典_加载的存储库;
i假定此[Type repositoryType]
{
得到
{
if(_loadedRepositories.ContainsKey(repositoryType))
{
返回_loadedRepositories[repositoryType];
}
var repository=GetFactory(repositoryType).CreateRepository(repositoryType,_context);
_添加(repositoryType,repository);
返回存储库;
}
}
IFilteredRepositoryFactory GetFactory(类型repositoryType)
{
//如果未找到存储库工厂,则引发异常
返回_repositoryFactories.First(x=>x.CanCreateRepository(repositoryType));
}
}

需要注意的是,新的
存储库将由第一个匹配的工厂实现创建。因此,如果工厂集合包含多个工厂,这些工厂可以为给定的存储库
类型
创建
存储库
,则将使用枚举中的第一个
IFilteredRepositoryFactory
对象,并忽略任何后续工厂。此外,如果没有注册的工厂,则会引发异常。

我通常会创建一次ObjectContext,并将其存储在线程本地存储中(使用NamedThreadDataSlot),然后从那里访问ObjectContext。这确保了ObjectContext在整个请求中共享,这将由一个线程处理。

RepositoryProvider似乎是个好主意。它看起来怎么样(伪代码),或者你能给我一个简单例子的链接吗?
public interface IRepositoryProvider
{
    IRepository this[Type repositoryType] { get; }
}
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));
    }
}