Note that there are some explanatory texts on larger screens.

plurals
  1. POMVC 3 - how to implement a service layer, do I need repositories?
    primarykey
    data
    text
    <p>I am currently building my first MVC 3 application, using EF Code First, SQL CE and Ninject. I have read a lot about using Repositories, Unit of Work and Service Layers. I think I have got the basics sorted out, and I have made my own implementation.</p> <p>This is my current setup:</p> <p><strong>Entities</strong></p> <pre><code>public class Entity { public DateTime CreatedDate { get; set; } public Entity() { CreatedDate = DateTime.Now; } } public class Profile : Entity { [Key] public Guid UserId { get; set; } public string ProfileName { get; set; } public virtual ICollection&lt;Photo&gt; Photos { get; set; } public Profile() { Photos = new List&lt;Photo&gt;(); } public class Photo : Entity { [Key] public int Id { get; set; } public Guid FileName { get; set; } public string Description { get; set; } public virtual Profile Profile { get; set; } public Photo() { FileName = Guid.NewGuid(); } } </code></pre> <p><strong>SiteContext</strong></p> <pre><code>public class SiteContext : DbContext { public DbSet&lt;Profile&gt; Profiles { get; set; } public DbSet&lt;Photo&gt; Photos { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove&lt;PluralizingTableNameConvention&gt;(); } } </code></pre> <p><strong>Interface: IServices</strong></p> <pre><code>public interface IServices : IDisposable { PhotoService PhotoService { get; } ProfileService ProfileService { get; } void Save(); } </code></pre> <p><strong>Implementation: Services</strong></p> <pre><code>public class Services : IServices, IDisposable { private SiteContext _context = new SiteContext(); private PhotoService _photoService; private ProfileService _profileService; public PhotoService PhotoService { get { if (_photoService == null) _photoService = new PhotoService(_context); return _photoService; } } public ProfileService ProfileService { get { if (_profileService == null) _profileService = new ProfileService(_context); return _profileService; } } public void Save() { _context.SaveChanges(); } private bool disposed = false; protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { _context.Dispose(); } } this.disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } </code></pre> <p><strong>Interface</strong></p> <pre><code>public interface IPhotoService { IQueryable&lt;Photo&gt; GetAll { get; } Photo GetById(int photoId); Guid AddPhoto(Guid profileId); } </code></pre> <p><strong>Implementation</strong></p> <pre><code>public class PhotoService : IPhotoService { private SiteContext _siteContext; public PhotoService(SiteContext siteContext) { _siteContext = siteContext; } public IQueryable&lt;Photo&gt; GetAll { get { return _siteContext.Photos; } } public Photo GetById(int photoId) { return _siteContext.Photos.FirstOrDefault(p =&gt; p.Id == photoId); } public Guid AddPhoto(Guid profileId) { Photo photo = new Photo(); Profile profile = _siteContext.Profiles.FirstOrDefault(p =&gt; p.UserId == profileId); photo.Profile = profile; _siteContext.Photos.Add(photo); return photo.FileName; } } </code></pre> <p><strong>Global.asax</strong></p> <pre><code>protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); Database.SetInitializer&lt;SiteContext&gt;(new SiteInitializer()); } </code></pre> <p><strong>NinjectControllerFactory</strong></p> <pre><code>public class NinjectControllerFactory : DefaultControllerFactory { private IKernel ninjectKernel; public NinjectControllerFactory() { ninjectKernel = new StandardKernel(); AddBindings(); } protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType); } private void AddBindings() { ninjectKernel.Bind&lt;IServices&gt;().To&lt;Services&gt;(); } } </code></pre> <p><strong>PhotoController</strong></p> <pre><code>public class PhotoController : Controller { private IServices _services; public PhotoController(IServices services) { _services = services; } public ActionResult Show(int photoId) { Photo photo = _services.PhotoService.GetById(photoId); if (photo != null) { string currentProfile = "Profile1"; _services.PhotoService.AddHit(photo, currentProfile); _services.Save(); return View(photo); } else { // Add error message to layout TempData["message"] = "Photo not found!"; return RedirectToAction("List"); } } protected override void Dispose(bool disposing) { _services.Dispose(); base.Dispose(disposing); } } </code></pre> <p>I can build my solution and it seems to be working correctly.</p> <p>My questions are:</p> <ol> <li>Are there any obvious flaws in my implementation that I am missing?</li> <li>Will I be able to use this with TDD? Usually I see mocking of repositories but I haven't used that in the above, will that cause issues?</li> <li>Am I using DI (Ninject) correctly and enough?</li> </ol> <p>I am a hobby programmer, so any comments and/or suggestions to my code are welcome!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload