正确处理控制器内的存储库对象

时间:2013-08-13 20:05:59

标签: asp.net-mvc dependency-injection repository-pattern dispose

我很难搞清楚这一点。我已经将Repository和Unit of Work模式实现为我的数据库的数据访问抽象。我正在使用依赖注入将它们注入控制器。问题是当控制器被丢弃时,它会处理存储库,但是当我刷新页面时,存储库中的DbContext对象为空(我认为不应该这样)。类的实现如下所示。

这是数据库存储库类:

public class ConferenceCrawlyDbRepository : IConferenceCrawlyDbRepository
{
    private ConferenceCrawlyDbContext _context = null;
    private static ConferenceCrawlyDbRepository _instance = null;

    public IRepository<AcademicDegree> AcademicDegrees { get; private set; }

    public IRepository<Conference> Conferences { get; private set; }

    public IRepository<ConferenceComment> ConferenceComments { get; private set; }

    public IRepository<ConferenceRating> ConferenceRatings { get; private set; }

    public IRepository<ConnectionConferenceRecommendation> ConnectionConferenceRecommendation { get; private set; }

    public IRepository<Country> Countries { get; private set; }

    public IRepository<ImportantDate> ImportantDates { get; private set; }

    public IRepository<Topic> Topics { get; private set; }

    public IRepository<UserProfile> UserProfiles { get; private set; }

    public IRepository<UserProfileSettings> UserProfileSettings { get; private set; }

    public IRepository<UsersConnection> UserConnections { get; private set; }

    public IRepository<Venue> Venues { get; private set; }

    private ConferenceCrawlyDbRepository(ConferenceCrawlyDbContext context)
    {
        _context = context;

        AcademicDegrees = new Repository<AcademicDegree>(context);
        Conferences = new Repository<Conference>(context);
        ConferenceComments = new Repository<ConferenceComment>(context);
        ConferenceRatings = new Repository<ConferenceRating>(context);
        ConnectionConferenceRecommendation = new Repository<ConnectionConferenceRecommendation>(context);
        Countries = new Repository<Country>(context);
        ImportantDates = new Repository<ImportantDate>(context);
        Topics = new Repository<Topic>(context);
        UserProfiles = new Repository<UserProfile>(context);
        UserProfileSettings = new Repository<UserProfileSettings>(context);
        UserConnections = new Repository<UsersConnection>(context);
        Venues = new Repository<Venue>(context);
    }

    public static ConferenceCrawlyDbRepository Instance
    {
        get
        {
            if (_instance == null)
                _instance = new ConferenceCrawlyDbRepository(new ConferenceCrawlyDbContext());

            return _instance;
        }
    }

    public bool CommitChanges()
    {
        try
        {
            return _context.SaveChanges() > 0;
        }
        catch
        {
            // TODO: Add logging
            return false;
        }
    }

    public void Dispose()
    {
        if (_context != null)
            _context.Dispose();
    }

这是通用存储库类:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private ConferenceCrawlyDbContext _context = null;
    private DbSet<TEntity> _dbSet = null;

    public Repository(ConferenceCrawlyDbContext context)
    {
        _context = context;
        _dbSet = context.Set<TEntity>();
    }

    public DbSet<TEntity> DbSet
    {
        get
        {
            return _dbSet;
        }
    }

    public bool Add(TEntity entity)
    {
        try
        {
            DbSet.Add(entity);

            return true;
        }
        catch (Exception ex)
        {
            // TODO: Add logging
            return false;
        }

    }

    public bool Update(TEntity entity)
    {
        try
        {
            var entry = _context.Entry<TEntity>(entity);

            DbSet.Attach(entity);

            entry.State = EntityState.Modified;

            return true;
        }
        catch(Exception ex)
        {
            // TODO: Add logging
            return false;
        }
    }

    public bool Remove(TEntity entity)
    {
        try
        {
            DbSet.Remove(entity);

            return true;
        }
        catch (Exception ex)
        {
            // TODO: Add logging
            return false;
        }
    }

    public IQueryable<TEntity> GetAll()
    {
        return DbSet;
    }

    public IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
    {
        return DbSet.Where(predicate);
    }

    public TEntity FindById(params object[] keys)
    {
        return DbSet.Find(keys);
    }

    public bool Contains(Expression<Func<TEntity, bool>> predicate)
    {
        return _dbSet.Any(predicate);
    }

    public bool CommitChanges()
    {
        try
        {
            return _context.SaveChanges() > 0;
        }
        catch
        {
            // TODO: Add logging
            return false;
        }
    }

    public void Dispose()
    {
        if (_context != null)
            _context.Dispose();
    }
}

这是依赖注入的自定义控制器工厂:

    public class CustomControllerFactory : DefaultControllerFactory
    {
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (controllerType != null)
            {
                if (controllerType.GetConstructor(new Type[] { typeof(IConferenceCrawlyDbRepository) }) != null)
                    return Activator.CreateInstance(controllerType, new object[] { ConferenceCrawlyDbRepository.Instance }) as Controller;
                else if (controllerType.GetConstructor(new Type[] { typeof(IConferenceCrawlyDbRepository), typeof(IMailService) }) != null)
                    return Activator.CreateInstance(controllerType, new object[] { ConferenceCrawlyDbRepository.Instance,
#if DEBUG
                     MockMailService.Instance
#else
                     MailService.Instance
#endif
                     }) as Controller;
            }

            return base.GetControllerInstance(requestContext, controllerType);
        }

最后,控制器及其动作:

public class HomeController : Controller
    {
        private IConferenceCrawlyDbRepository _dbRepository;
        private IMailService _mailService;

        public HomeController(IConferenceCrawlyDbRepository dbRepository, IMailService mailService)
        {
            _dbRepository = dbRepository;
            _mailService = mailService;
        }

        //
        // GET: /
        public ActionResult Index()
        {
            var countries = _dbRepository.Countries.GetAll().ToList();

            return View(countries);
        }

        //
        // GET: /Home/About
        public ActionResult About()
        {
            return View();
        }

        //
        // GET: /Home/Contact
        public ActionResult Contact()
        {
            return View(new Contact());
        }

        //
        // POST: /Home/Contact
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Contact(Contact contact)
        {
            if (ModelState.IsValid)
            {
                if (await _mailService.SendMail(contact.Email, contact.Title,
                    String.Format("{1}{0}{2}", Environment.NewLine, contact.Message, String.IsNullOrEmpty(contact.Name) ? "Anonimous" : contact.Name)))
                {
                    ViewBag.SuccessMessage = "Comment has been successfully sent.";

                    return View(new Contact());
                }
                else
                    ViewBag.ErrorMessage = "Couldn't send your email. Please try again later";
            }

            return View(contact);
        }

        protected override void Dispose(bool disposing)
        {
            if (_dbRepository != null)
                _dbRepository.Dispose();

            base.Dispose(disposing);
        }
    }

当我调用存储库时,异常会在索引操作中抛出,但只有在第一次访问此控制器之后,它才会在存储库中显示DbContext对象。我显然做错了什么,但我无法理解。

1 个答案:

答案 0 :(得分:0)

经过长时间的盯着和调试代码,我弄明白了。这很简单,因为我在ConferenceCrawlyDbRepository中处理上下文我还应该设置_instance对象,它使用它来为null,然后它将与DbContext对象一起重新创建。我现在摔得太傻了......