简体   繁体   English

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

[英]C#/EF and the Repository Pattern: Where to put the ObjectContext in a solution with multiple repositories?

I have multiple repositories in my application. 我的应用程序中有多个存储库。 Where should I put the ObjectContext? 我应该把ObjectContext放在哪里? Right now, I have a reference like ObjectContext ctx; 现在,我有一个像ObjectContext ctx;的引用ObjectContext ctx; in every repository. 在每个存储库中。 What is the smartest and safest way to go about this? 什么是最聪明,最安全的方法?

A design with multiple ObjectContext instances is only acceptable if your Repository methods commit the transaction. 只有在Repository方法提交事务时,才能接受具有多个ObjectContext实例的设计。 Otherwise, it is possible that external calls to commit the transaction may not persist everything you intend, because you will hold references to different instances of the ObjectContext . 否则,提交事务的外部调用可能无法保留您想要的所有内容,因为您将保留对ObjectContext不同实例的引用。

If you want to restrict the ObjectContext to a single instance, then you can build a RepositoryProvider class that contains the ObjectContext , and manages the propagation of repository actions to data commits. 如果要将ObjectContext限制为单个实例,则可以构建包含ObjectContextRepositoryProvider类,并管理存储库操作到数据提交的传播。 This can be best accomplished by either, - Injecting the ObjectContext reference into each repository, or - Subscribing the repositories' events to EventHandler s that call the appropriate methods on the ObjectContext . 这可以通过以下方式实现: - 将ObjectContext引用注入每个存储库,或者 - 将存储库事件订阅到调用ObjectContext上相应方法的EventHandler

The following is a highly pluggable implementation that I have used: 以下是我使用的高度可插拔的实现:

Repository Provider Interface 存储库提供程序接口

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

Repository Factory Interface 存储库工厂接口

The implementation has dependency on an IEnumerable<IFilteredRepositoryFactory> . 该实现依赖于IEnumerable<IFilteredRepositoryFactory>

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

So, the implementation looks like: 所以,实现看起来像:

Repository Provider Class 存储库提供程序类

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));
    }
}

It should be noted that a new Repository will be created by the first matching factory implementation. 应该注意的是,第一个匹配的工厂实现将创建一个新的Repository So, if the collection of factories contains multiple factories that can create a Repository for the given repository Type , the first IFilteredRepositoryFactory object in the enumerable will be used and any subsequent factories will be ignored. 因此,如果工厂集合包含多个可以为给定存储库Type创建Repository工厂,则将使用可枚举中的第一个IFilteredRepositoryFactory对象,并且将忽略任何后续工厂。 In addition, if there is no registered factory, and exception will be thrown. 另外,如果没有注册工厂,则会抛出异常。

What I Normally do is create a ObjectContext once and store it in Thread Local Storage (using NamedThreadDataSlot) and access the ObjectContext from there. 我通常做的是创建一个ObjectContext并将其存储在线程本地存储中(使用NamedThreadDataSlot)并从那里访问ObjectContext。 This ensures that the ObjectContext is shared across the request, which will be handled by one thread. 这确保了ObjectContext在请求中共享,该请求将由一个线程处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM