当前位置: 动力学知识库 > 问答 > 编程问答 >

asp.net mvc - Proper disposal of repository object inside controller

问题描述:

I am having a hard time figuring this out. I have implemented Repository and Unit of Work patterns as a data access abstraction for my database. I am using Dependency Injection to inject them into the controller. The problem is when the controller is disposed, it disposes the repository, but then when I refresh the page, DbContext object inside repository is null (it shouldn't be, I think). The implementation of classes is shown below.

This is the database Repository class:

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

}

And this is the generic repository class:

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

}

}

Here is my custom controller factory for dependency injection:

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

}

And finally, controller with its action:

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

}

}

The Exception is thrown inside index action when I call the repository, but only after the first time accessing this controller and it says that DbContext object inside repository. I am obviously doing something wrong, but I can't figure it out.

网友答案:

I figure it out after long staring and debugging of code. It's so simple, because I'm disposing context inside ConferenceCrawlyDbRepository I should also set _instance object which is using it to null, and then it will be recreated along with DbContext object. I fell so stupid right now...

分享给朋友:
您可能感兴趣的文章:
随机阅读: