I am having hard time using Repository patterns, is it possible to create two repository patterns?? One for products, another for orders??
I failed to connect these repositories to databases. I know how to work with one repository, but two with IRepository where T: Entity I am getting lost. The question is whether I can create and will not volatile the rules if create ProductRepository and OrderRepository?
Repository pattern is widely used in DDD (Domain-Driven-Design) you could check it here: http://www.infoq.com/minibooks/domain-driven-design-quickly. Also check this book: http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215
With regards to your question:
Yes you can use more than 1 repository. Look in this example I use nHibernate session:
// crud operations
public abstract class Repository<T> : IRepository<T> where T : class
{
protected readonly ISession _session;
public Repository(ISession session)
{
_session = session;
}
public T Add(T entity)
{
_session.BeginTransaction();
//_session.SaveOrUpdate(entity);
_session.Save(entity);
_session.Transaction.Commit();
return entity;
}
//...
}
public interface IRepository<T>
{
T Add(T entity);
T Update(T entity);
T SaveOrUpdate(T entity);
bool Delete(T entity);
}
Then my repository looks like this:
public class ProjectRepository : Repository<Project>, IProjectRepository
{
// Project specific operations
}
public interface IProjectRepository : IRepository<Project>
{
Project Add(Project entity);
Project Update(Project entity);
Project find_by_id(int id);
Project find_by_id_and_user(int id, int user_id);
//..
}
Then using Ninject:
Global.asax.cs
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}
Then in NinjectControllerFactory I load the modules:
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel kernel = new StandardKernel(new NhibernateModule(), new RepositoryModule(), new DomainServiceModule());
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
//var bindings = kernel.GetBindings(typeof(IUserService));
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
}
NhibernateModule:
public class NhibernateModule : NinjectModule
{
public override void Load()
{
string connectionString =
ConfigurationManager.ConnectionStrings["sqlite_con"].ConnectionString;
var helper = new NHibernateHelper(connectionString);
Bind<ISessionFactory>().ToConstant(helper.SessionFactory).InSingletonScope();
Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
}
}
Then in RepositoryModule I use Ninject Conventions to automatically bind all repositories with their interfaces:
using Ninject.Extensions.Conventions;
public class RepositoryModule : NinjectModule
{
public override void Load()
{
IKernel ninjectKernel = this.Kernel;
ninjectKernel.Scan(kernel =>
{
kernel.FromAssemblyContaining<ProjectRepository>();
kernel.BindWithDefaultConventions();
kernel.AutoLoadModules();
kernel.InRequestScope();
});
}
}
And in the end I basically inject Repository in the controller:
public class projectscontroller : basecontroller
{
private readonly IProjectRepository _projectRepository;
public projectscontroller(IProjectRepository projectRepository)
{
_projectRepository = projectRepository;
}
[AcceptVerbs(HttpVerbs.Get)]
[Authorize]
public ActionResult my()
{
int user_id = (User as CustomPrincipal).user_id;
var projectList = _projectRepository.find_by_user_order_by_date(user_id);
var projetsModel = new ProjectListViewModel(projectList);
return View("my", projetsModel);
}
}
This way you just create new Repository and its Interface and it will be automatically injected to your controller.
Related
I am trying to implement Dependency Injection with Autofac in an ASP.NET MVC5 Project. But I am getting the following error every time:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyProjectName.DAL.Repository` ........
My Autofac configuration code in App_Start folder as follows:
public static class IocConfigurator
{
public static void ConfigureDependencyInjection()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<Repository<Student>>().As<IRepository<Student>>();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
In Global.asax file:
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
// Other MVC setup
IocConfigurator.ConfigureDependencyInjection();
}
}
Here is my IRepository:
public interface IRepository<TEntity> where TEntity: class
{
IQueryable<TEntity> GelAllEntities();
TEntity GetById(object id);
void InsertEntity(TEntity entity);
void UpdateEntity(TEntity entity);
void DeleteEntity(object id);
void Save();
void Dispose();
}
Here is my Repository:
public class Repository<TEntity> : IRepository<TEntity>, IDisposable where TEntity : class
{
internal SchoolContext context;
internal DbSet<TEntity> dbSet;
public Repository(SchoolContext dbContext)
{
context = dbContext;
dbSet = context.Set<TEntity>();
}
.....................
}
Here is my Student Controller:
public class StudentController : Controller
{
private readonly IRepository<Student> _studentRepository;
public StudentController()
{
}
public StudentController(IRepository<Student> studentRepository)
{
this._studentRepository = studentRepository;
}
....................
}
What's wrong in my Autofac Configuration..Any Help Please??
To inject a dependency you need to have satisfied all of the dependencies for all of the pieces down the chain.
In your case, the Repository constructor cannot be satisfied without a SchoolContext.
So in your registration add:
builder.RegisterType<SchoolContext>().InstancePerRequest();
See http://docs.autofac.org/en/latest/lifetime/instance-scope.html#instance-per-request
I am having a project and my project is connecting to two different databases are BookStoreEntities and BlogEntities.
If I remove line code builder.RegisterType<BlogEntities>().As<DbContext>(); in Autofac configuration my project works fine and else I'll get error "The entity type Book is not part of the model for the current context".
My autofac config:
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<BookStoreEntities>().As<DbContext>();
builder.RegisterType<BlogEntities>().As<DbContext>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerDependency();
builder.RegisterType<BookService>().As<IBookService>();
builder.RegisterFilterProvider();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
Repository class:
public class Repository<T> : IRepository<T> where T : class
{
private DbContext _dbContext;
private DbSet<T> _dbSet;
public Repository(DbContext dbContext)
{
_dbContext = dbContext;
_dbSet = dbContext.Set<T>();
}
public IEnumerable<T> GetAll()
{
return _dbSet;
}
}
Service layer:
public class BookService : IBookService
{
private IRepository<Book> _bookRepository;
public BookService(IRepository<Book> bookRepository)
{
_bookRepository = bookRepository;
}
public IEnumerable<Book> GetBooks()
{
return _bookRepository.GetAll();
}
}
Controller:
public class BookController : Controller
{
private IBookService _bookService;
public BookController(IBookService bookService)
{
_bookService = bookService;
}
// GET: Book
public ActionResult Index()
{
var books = _bookService.GetBooks();
return View(books);
}
}
My Project is using 2 different databases and Service layer will implement from this Generic Repository. I want to myservice1 works with MyDbContext1 and myservice2 works with MyDbContext2
Then don't new your DbContext inside your repository. That makes testing hard anyway.
Inject it:
public Repository(DbContext dbContext)
{
_dbContext = dbContext;
}
Now the repository doesn't care which DbContext-derived class is injected. This works because you only call DbContext.Set<T>().
Try to something like:
public class MyDbContext1 : DbContext
{
public MyDbContext1 ()
:base("ConnectionString")
{ }
public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
{
return base.Set<TEntity>();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//...
}
}
And add to repository new property
private IDbSet<T> Entities
{
get
{
if (_dbSet == null)
{
_dbSet = _dbContext1.Set<T>();
}
return _dbSet;
}
}
I have below code which will work without any issue
MAUserController.cs
public class MAUserController : ApiController
{
ILogService loggerService;
IMAUserService _service;
public MAUserController(ILogService loggerService, IMAUserService Service)
{
this.loggerService = loggerService;
this._service = Service;
}
}
DependencyInstaller.cs
public class DependencyInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ILogService>().ImplementedBy<LogService>().LifeStyle.PerWebRequest,
Component.For<IDatabaseFactory>().ImplementedBy<DatabaseFactory>().LifeStyle.PerWebRequest,
Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>().LifeStyle.PerWebRequest,
AllTypes.FromThisAssembly().BasedOn<IHttpController>().LifestyleTransient(),
AllTypes.FromAssemblyNamed("ISOS.Health.Service").Where(type => type.Name.EndsWith("Service")).WithServiceAllInterfaces().LifestylePerWebRequest(),
AllTypes.FromAssemblyNamed("ISOS.Health.Repository").Where(type => type.Name.EndsWith("Repository")).WithServiceAllInterfaces().LifestylePerWebRequest()
);
}
}
If I am using normal Controller instead ApiController then it gives me an error
UserController.cs
public class UserController : Controller
{
ILogService loggerService;
IMAUserService _service;
public UserController(ILogService loggerService, IMAUserService Service)
{
this.loggerService = loggerService;
this._service = Service;
}
}
This will give an error:
No parameterless constructor defined for this object
I am using CastleDI Windsor for Dependency injection.
Do I need to do anything or register something?
FIRST APPROACH
Advice: Use with caution, because it may cause memory leaks for Castle Windsor.
You have to create a controller activator, which should implement the IControllerActivator interface, in order to use your DI container to create the controller instances:
public class MyWindsorControllerActivator : IControllerActivator
{
public MyWindsorControllerActivator(IWindsorContainer container)
{
_container = container;
}
private IWindsorContainer _container;
public IController Create(RequestContext requestContext, Type controllerType)
{
return _container.Resolve(controllerType) as IController;
}
}
Then, add this class to your DependencyInstaller:
public class DependencyInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
// Current code...
Component.For<IControllerActivator>()
.ImplementedBy<MyWindsorControllerActivator>()
.DependsOn(Dependency.OnValue("container", container))
.LifestyleSingleton();
);
}
}
Also, create your own dependency resolver based on the Windsor container:
public class MyWindsorDependencyResolver : IDependencyResolver
{
public MyWindsorDependencyResolver(IWindsorContainer container)
{
_container = container;
}
private IWindsorContainer _container;
public object GetService(Type serviceType)
{
return _container.Resolve(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.ResolveAll(serviceType).Cast<object>();
}
}
Then, finally, register your dependency resolver in the Application_Start method in Global.asax.cs:
DependencyResolver.SetResolver(new MyWindsorDependencyResolver(windsorContainer));
This way, when MVC requires the controller activator through it's dependency resolver, it will get ours, which will use our Windsor container to create the controllers with all it's dependencies.
In order to avoid memory leaks using IControllerActivator, the easiest solution will be to use lifestyles like per thread or per web request, rather than the default (Singleton), transient and pooled, for the registered components. Check this link for more info about how to avoid memory leaks using Castle Windsor Container.
SECOND APPROACH
However, as pointed out by #PhilDegenhardt, a much better and correct approach will be to implement a custom controller factory, in order to be able to release the controller component created by the Castle Windsor DI Container. Here you can find an example (see the section about Dependency Injection).
Taken from that example, the implementation could be:
Global.asax.cs:
public class MvcApplication : System.Web.HttpApplication
{
private WindsorContainer _windsorContainer;
protected void Application_Start()
{
var _windsorContainer = new WindsorContainer();
_windsorContainer.Install(
new DependencyInstaller(),
// Other installers...
);
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_windsorContainer.Kernel));
}
protected void Application_End()
{
if (_windsorContainer != null)
{
_windsorContainer.Dispose();
}
}
}
WindsorControllerFactory.cs:
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public WindsorControllerFactory(IKernel kernel)
{
_kernel = kernel;
}
public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller); // The important part: release the component
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
return (IController)_kernel.Resolve(controllerType);
}
}
Look at the following project link https://github.com/rarous/Castle.Windsor.Web.Mvc
Add this reference via NuGet to your MVC project, it will do the registering job for you.
Do not forget to catch your errors in global.asax.cs!
Registration :
container.Register(Component.For<IControllerFactory>().ImplementedBy<WindsorControllerFactory>());
Implementation of MVC controller factory :
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Castle.MicroKernel;
namespace Installer.Mvc
{
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public WindsorControllerFactory(IKernel kernel)
{
_kernel = kernel;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
if (_kernel.GetHandler(controllerType) != null)
{
return (IController)_kernel.Resolve(controllerType);
}
return base.GetControllerInstance(requestContext, controllerType);
}
public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller);
}
}
}
I created a project using MVC3 - Entity Framework. I like to use Repository Pattern together with it. I am new to repository pattern. Do I need to create ONE EACH Repository for each Model Class (classes which represent each table in the database) and within each repository do I have to write all the functions which will Insert, Update, Delete and Fetch record?
No you don't. You can implement a GenericRepository for all your classes and then override it if you need to add functions. First i am gonna show you the unit of work. Through this class you can access all the repositories. I have added to this example one generic and one overrided:
public class UnitOfWork
{
FBDbContext context = new FBDbContext();
public FBDbContext Context { get { return context; } }
private BlockRepository BlockRepository;
private GenericRepository<Category> CategoryRepository;
#region RepositoryClasses
public IBlockRepository blockRepository
{
get
{
if (this.BlockRepository == null)
this.BlockRepository = new BlockRepository(context);
return BlockRepository;
}
}
public IGenericRepository<Category> categoryRepository
{
get
{
if (this.CategoryRepository == null)
this.CategoryRepository = new GenericRepository<Category>(context);
return CategoryRepository;
}
}
#endregion
public void Save()
{
context.SaveChanges();
}
}
Then you have the generic repository:
public class GenericRepository<TEntity>
{
internal FBDbContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(FBDbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual TEntity Create()
{
return Activator.CreateInstance<TEntity>();
}
public IQueryable<TEntity> GetAll()
{
return dbSet;
}
//And all the functions you want in all your model classes...
}
and an example when you want to override the generic repository:
public class BlockRepository : GenericRepository<Block>
{
public BlockRepository(FBDbContext context) : base(context) { }
public IEnumerable<Block> GetByCategory(Category category)
{
return context.Blocks.Where(r => r.CategoryId == category.Id);
}
}
You can create common repository which will have common methods, all other repositories will be it's children:
public class MyModelRepository : GenericRepository<MyModel>
{
// extend
}
var MyModelRepository = new MyModelRepository();
See this, or google for "Generic Repository" :). If your don't need extended functionality for some model repository, then you can even not create repository class, instead do something like this:
var MyModelRepository = new GenericRepository<MyModel>();
Have an interface that represents the common operations between each repository. I.e. Insert, Update, Delete and Fetch:
public interface IRepository<T>
{
void Insert(T entity);
void Delete(T entity);
void Update(T entity);
void Fetch(T entity);
}
public class Repository<T> : IRepository<T>
/// your implementation
}
Then in each model you could define the repository to suit the context, for instance:
var repository1 = new Repository<ModelType>(dataContext);
repository1.Insert(obj);
var repository2 = new Repository<DifferentModelType>(dataContext);
repository2.Fetch(objects);
http://www.remondo.net/repository-pattern-example-csharp/
I'm trying to work with NInject in my MVC 3 application, and i have one question.
Interface
public interface ITalesRepository
{
IEnumerable<Tale> GetAllTales();
}
Repository
public class TalesRepository : ITalesRepository
{
private FairyTalesMVC3DataContext _dataContext;
public TalesRepository(FairyTalesMVC3DataContext dataContext)
{
_dataContext = dataContext;
}
public IEnumerable<Tale> GetAllTales()
{
return _dataContext.Tales.OrderBy(c => c.NameAn);
}
}
Home controller
public class HomeController : Controller
{
private readonly ITalesRepository _talesRepository;
public HomeController(ITalesRepository talesRepository)
{
_talesRepository = talesRepository;
}
public ActionResult Index()
{
ViewBag.Tales = _talesRepository.GetAllTales();
return View();
}
}
So, i need to initialize my TalesRepository with DataContext, and now it is so:
private void RegisterDependencyResolver()
{
var kernel = new StandardKernel();
kernel.Bind<ITalesRepository>().To<TalesRepository>().WithConstructorArgument("dataContext", new FairyTalesMVC3DataContext(ConfigurationManager.ConnectionStrings["dbFairyTalesConnectionString"].ConnectionString));
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}
So, my question, is it ok or something wrong?
First of all:
public IEnumerable<Tale> GetAllTales()
{
return _dataContext.Tales.OrderBy(c => c.NameAn);
}
I would add .ToList() to the end. Else you'll get data layer exceptions in your presentation layer which is not fine.
Next, I would recommend that you switch to ViewModels instead of using ViewBag. It's a lot easier to prevent that logic leaks into the views if you are using ViewModels. Since you can add the logic to the ViewModel and thus get the same behaviour in all views using the model.
Your application should inherit from NinjectHttpApplication. It registers dependency resolver, so you don't have to do it.
You should also override CreateKernel in application class and register your own module with bindings:
public class MvcApplication : NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
return new StandardKernel(new INinjectModule[] {new MvcModule()});
}
}
public class MvcModule : NinjectModule
{
public override void Load()
{
Bind<ITalesRepository>().To<TalesRepository>();
Bind<FairyTalesMVC3DataContext>().To<FairyTalesMVC3DataContext>().InRequestScope();
}
}