C#/ EF和存储库模式:将ObjectContext放在具有多个存储库的解决方案中的位置?
我的应用程序中有多个存储库。 我应该在哪里放置ObjectContext? 现在,我有一个像ObjectContext ctx;
的引用ObjectContext ctx;
在每个存储库中。 什么是最聪明,最安全的方法?
只有Repository
方法提交事务时,才能接受具有多个ObjectContext
实例的设计。 否则,提交事务的外部调用可能无法保留您想要的所有内容,因为您将保留对ObjectContext
不同实例的引用。
如果要将ObjectContext
限制为单个实例,则可以构建包含ObjectContext
的RepositoryProvider
类,并管理存储库操作到数据提交的传播。 这可以通过以下方式实现: – 将ObjectContext
引用注入每个存储库,或者 – 将存储库事件订阅到调用ObjectContext
上相应方法的EventHandler
。
以下是我使用的高度可插拔的实现:
存储库提供程序接口
public interface IRepositoryProvider { IRepository this[Type repositoryType] { get; } }
存储库工厂接口
该实现依赖于IEnumerable
。
public interface IFilteredRepositoryFactory{ bool CanCreateRepository(Type repositoryType); IRepository CreateRepository(Type repositoryType, ObjectContext context); }
所以,实现看起来像:
存储库提供程序类
public class RepositoryProvider { public RepositoryProvider(ObjectContext context, IEnumerable repositoryFactories) { _context = context; _repositoryFactories = repositoryFactories; } private readonly ObjectContext _context; private readonly IEnumerable _repositoryFactories; private readonly Dictionary _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
。 因此,如果工厂集合包含可以为给定存储库Type
创建Repository
多个工厂,则将使用可枚举中的第一个IFilteredRepositoryFactory
对象,并且将忽略任何后续工厂。 另外,如果没有注册工厂,则会抛出exception。
我通常做的是创建一个ObjectContext并将其存储在线程本地存储中(使用NamedThreadDataSlot)并从那里访问ObjectContext。 这确保了ObjectContext在请求中共享,这将由一个线程处理。