Hello again. I'm going to post a short (hopefully) sample of my implementation. It seems to work, but I'm not sure if it's doing everything it should nor do I fully understand it, myself.
I have this UnitOfWork interface:
/// <summary>
/// Unit of Work Contract
/// </summary>
public interface IUnitOfWork
{
/// <summary>
/// Commits the changes to the data store.
/// </summary>
void Commit();
}
and this UnitOfWork class:
public class UnitOfWork : IUnitOfWork, IDisposable
{
/// <summary>
/// The MyAppContext contract
/// </summary>
private readonly MyAppContext _context;
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
if (_context != null)
{
_context.Dispose();
}
GC.SuppressFinalize(this);
}
/// <summary>
/// Commits the changes to the data store.
/// </summary>
public void Commit()
{
_context.SaveChanges();
}
public UnitOfWork(MyAppContext context)
{
_context = context;
}
}
I also have this Repository, which implements a couple interfaces:
public class PhoneLabelRepository : GenericRepository<PhoneLabel>, IPhoneLabelRepository
{
public PhoneLabelRepository(MyAppContext context) : base(context)
{
}
}
I do some binding with Ninject:
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel kernel = new StandardKernel(new MyAppServices());
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
private class MyAppServices : NinjectModule
{
public override void Load()
{
Bind<IUnitOfWork>().To<UnitOfWork>();
Bind<IPhoneLabelRepository>().To<PhoneLabelRepository>();
}
}
}
and set the Controller Factory on application start:
MyAppContext db = new MyAppContext();
UnitOfWork unitOfWork = new UnitOfWork(db);
PhoneLabel p = new PhoneLabel { Label = "Test" };
var phoneLabelRepository = new PhoneLabelRepository(db);
phoneLabelRepository.Add(p);
unitOfWork.Commit();
var phoneLabels = phoneLabelRepository.All();
The new PhoneLabel is saved and phoneLabels contains all the rows from the database. I put this together after reviewing several code samples/tutorials, but I can't help but think that it isn't the best way to do this or might not even be functioning the
way I think it is.
I see no reason to combine Unit Of Work and Repository patterns (maybe make the GenericRepository to implement IUnitOfWork) as your implementation of Unit Of Work does nothing. You can easily move the SaveChanges in the GenericRepository and you're done.
Also create the context inside the repository or use DI to inject it but do not create the Context in the Action then pass it along in the repository.
Please click 'Mark as Answer' if my reply has assisted you
I see no reason to combine Unit Of Work and Repository patterns (maybe make the GenericRepository to implement IUnitOfWork) as your implementation of Unit Of Work does nothing. You can easily move the SaveChanges in the GenericRepository and your done. Also
create the context inside the repository or use DI to inject it but do not create the Context in the Action then pass it along in the repository.
Regarding your comment, "the AppContext should implement IUnitOfWork...". Let's say I have the following AppContext:
public class MyAppContext : DbContext
{
public DbSet<Administrator> Administrators { get; set; }
public DbSet<Attachment> Attachments { get; set; }
public DbSet<Country> Countries { get; set; }
public DbSet<Language> Languages { get; set; }
public DbSet<Notice> Notices { get; set; }
public DbSet<Organization> Organizations { get; set; }
public DbSet<Person> People { get; set; }
public DbSet<PhoneLabel> PhoneLabels { get; set; }
public DbSet<Region> Regions { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<UserGroup> UserGroups { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
I should be implementing the IUnitOfWork here?
I'm having a hard time wrapping my head around the actual implementation of repository pattern and unit of work pattern in combination of DI. There seem to be so many different ways to do it, but hard to implement any without a thorough understanding of
what's actually going on.
I'n my opinion the simplest way is to use MvcScaffolding package from NuGet that generates Repositories for your models you'll see that it generates something like this:
publicinterfaceIQuestionRepository
{
IQueryable<Question> All { get; }
IQueryable<Question> AllIncluding( paramsExpression<Func<Question , object>>[ ] includeProperties );
Question Find( int id );
void InsertOrUpdate( Question question );
void Delete( int id );
void Save( );
}
and the implementation:
publicclassQuestionRepository : IQuestionRepository
{
StarRatingContext context =newStarRatingContext( );
publicIQueryable<Question> All
{
get { return context.Questions; }
}
publicIQueryable<Question> AllIncluding( paramsExpression<Func<Question , object>>[ ] includeProperties )
{
IQueryable<Question> query = context.Questions;
foreach ( var includeProperty in includeProperties )
{
query = query.Include( includeProperty );
}
return query;
}
publicQuestion Find( int id )
{
return context.Questions.Find( id );
}
publicvoid InsertOrUpdate( Question question )
{
if ( question.Id ==default( int ) )
{
// New entity
context.Questions.Add( question );
}
else
{
// Existing entity
context.Questions.Attach( question );
context.Entry( question ).State =EntityState.Modified;
}
}
publicvoid Delete( int id )
{
var question = context.Questions.Find( id );
context.Questions.Remove( question );
}
publicvoid Save( )
{
context.SaveChanges( );
}
}
As you can see the Repository is the "UnitOfWork".
I use IQuestionRepository in my controller and inject the QuestionRepository implementation using DI.
The intention of the Unit Of Work pattern is to track the data integrity more like an assistance. It should be using the Repository pattern to do the persistance.
getoutofmyla...
Member
167 Points
107 Posts
Ninject + Repository Pattern + Unit of Work - Does this look right?
May 02, 2011 06:26 PM|LINK
Hello again. I'm going to post a short (hopefully) sample of my implementation. It seems to work, but I'm not sure if it's doing everything it should nor do I fully understand it, myself.
I have this UnitOfWork interface:
/// <summary> /// Unit of Work Contract /// </summary> public interface IUnitOfWork { /// <summary> /// Commits the changes to the data store. /// </summary> void Commit(); }and this UnitOfWork class:
public class UnitOfWork : IUnitOfWork, IDisposable { /// <summary> /// The MyAppContext contract /// </summary> private readonly MyAppContext _context; /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { if (_context != null) { _context.Dispose(); } GC.SuppressFinalize(this); } /// <summary> /// Commits the changes to the data store. /// </summary> public void Commit() { _context.SaveChanges(); } public UnitOfWork(MyAppContext context) { _context = context; } }I also have this Repository, which implements a couple interfaces:
public class PhoneLabelRepository : GenericRepository<PhoneLabel>, IPhoneLabelRepository { public PhoneLabelRepository(MyAppContext context) : base(context) { } }I do some binding with Ninject:
public class NinjectControllerFactory : DefaultControllerFactory { private IKernel kernel = new StandardKernel(new MyAppServices()); protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { if (controllerType == null) return null; return (IController)kernel.Get(controllerType); } private class MyAppServices : NinjectModule { public override void Load() { Bind<IUnitOfWork>().To<UnitOfWork>(); Bind<IPhoneLabelRepository>().To<PhoneLabelRepository>(); } } }and set the Controller Factory on application start:
Finally, in my controller, I can do this:
MyAppContext db = new MyAppContext(); UnitOfWork unitOfWork = new UnitOfWork(db); PhoneLabel p = new PhoneLabel { Label = "Test" }; var phoneLabelRepository = new PhoneLabelRepository(db); phoneLabelRepository.Add(p); unitOfWork.Commit(); var phoneLabels = phoneLabelRepository.All();The new PhoneLabel is saved and phoneLabels contains all the rows from the database. I put this together after reviewing several code samples/tutorials, but I can't help but think that it isn't the best way to do this or might not even be functioning the way I think it is.
I appreciate any guidance
raduenuca
All-Star
24675 Points
4250 Posts
Re: Ninject + Repository Pattern + Unit of Work - Does this look right?
May 03, 2011 06:31 AM|LINK
I see no reason to combine Unit Of Work and Repository patterns (maybe make the GenericRepository to implement IUnitOfWork) as your implementation of Unit Of Work does nothing. You can easily move the SaveChanges in the GenericRepository and you're done. Also create the context inside the repository or use DI to inject it but do not create the Context in the Action then pass it along in the repository.
Radu Enuca | Blog
getoutofmyla...
Member
167 Points
107 Posts
Re: Ninject + Repository Pattern + Unit of Work - Does this look right?
May 03, 2011 12:05 PM|LINK
Thanks
raduenuca
All-Star
24675 Points
4250 Posts
Re: Ninject + Repository Pattern + Unit of Work - Does this look right?
May 04, 2011 05:12 AM|LINK
In you link the Save method is in the generic repository (interface in their case) as I said.
I see no reason in your implementation not in general (sorry if I wasn't very explicit). See here another aproach:
http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx
So moving back to your code the AppContext should implement IUnitOfWork not another class that gets the AppContext as a parameter.
Here is another interesting implementation:
http://www.codeinsanity.com/2008/09/unit-of-work-pattern.html
Radu Enuca | Blog
getoutofmyla...
Member
167 Points
107 Posts
Re: Ninject + Repository Pattern + Unit of Work - Does this look right?
May 04, 2011 11:13 AM|LINK
Thanks for clarifying. I understand what you were saying now. Will check out those links.
getoutofmyla...
Member
167 Points
107 Posts
Re: Ninject + Repository Pattern + Unit of Work - Does this look right?
May 04, 2011 01:42 PM|LINK
Regarding your comment, "the AppContext should implement IUnitOfWork...". Let's say I have the following AppContext:
public class MyAppContext : DbContext { public DbSet<Administrator> Administrators { get; set; } public DbSet<Attachment> Attachments { get; set; } public DbSet<Country> Countries { get; set; } public DbSet<Language> Languages { get; set; } public DbSet<Notice> Notices { get; set; } public DbSet<Organization> Organizations { get; set; } public DbSet<Person> People { get; set; } public DbSet<PhoneLabel> PhoneLabels { get; set; } public DbSet<Region> Regions { get; set; } public DbSet<User> Users { get; set; } public DbSet<UserGroup> UserGroups { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); } }I should be implementing the IUnitOfWork here?
I'm having a hard time wrapping my head around the actual implementation of repository pattern and unit of work pattern in combination of DI. There seem to be so many different ways to do it, but hard to implement any without a thorough understanding of what's actually going on.
raduenuca
All-Star
24675 Points
4250 Posts
Re: Ninject + Repository Pattern + Unit of Work - Does this look right?
May 04, 2011 01:49 PM|LINK
I'n my opinion the simplest way is to use MvcScaffolding package from NuGet that generates Repositories for your models you'll see that it generates something like this:
and the implementation:
As you can see the Repository is the "UnitOfWork".
I use IQuestionRepository in my controller and inject the QuestionRepository implementation using DI.
You can find more about MvcScaffolding here:
http://blog.stevensanderson.com/
Radu Enuca | Blog
getoutofmyla...
Member
167 Points
107 Posts
Re: Ninject + Repository Pattern + Unit of Work - Does this look right?
May 04, 2011 02:10 PM|LINK
hmm..I think, for now, I will try that out. I can always change it later when I have more knowledge on the subject.
raduenuca
All-Star
24675 Points
4250 Posts
Re: Ninject + Repository Pattern + Unit of Work - Does this look right?
May 05, 2011 05:23 AM|LINK
and you can customize the scaffolder to generate the code how you want it
Radu Enuca | Blog
castlehills
Member
259 Points
171 Posts
Re: Ninject + Repository Pattern + Unit of Work - Does this look right?
May 05, 2011 10:55 AM|LINK
The intention of the Unit Of Work pattern is to track the data integrity more like an assistance. It should be using the Repository pattern to do the persistance.