C#/EF和存储库模式:在具有多个存储库的解决方案中,将ObjectContext放在何处?
我的应用程序中有多个存储库。我应该将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-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));
}
}