Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
625 views
in Technique[技术] by (71.8m points)

entity framework - 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? Right now, I have a reference like ObjectContext ctx; in every repository. What is the smartest and safest way to go about this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A design with multiple ObjectContext instances is only acceptable if your Repository methods commit the transaction. 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.

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. This can be best accomplished by either, - Injecting the ObjectContext reference into each repository, or - Subscribing the repositories' events to EventHandlers that call the appropriate methods on the ObjectContext.

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>.

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. 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. In addition, if there is no registered factory, and exception will be thrown.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...