My project is using MVC5, EF6 and Ninject.
I have some service classes wich composes the business layer, and only them are allowed to acces the DbContext, meaning that the controller doesen't have any direct access to the context.
The service classes are like those:
public interface IService1: IDisposable
{
IEnumerable<SomeDataType> GetSomeData(string param);
void SaveData();
}
public class Service1: IService1
{
private MyContext context;
public Maestri(MyContext context)
{
this.context = context;
}
public void Dispose()
{
context.Dispose();
}
public IEnumerable<SomeDataType> GetSomeData(string Param)
{
[...]
}
public void SaveData()
{
[...]
context.SaveChanges()
}
}
public interface IService2: IDisposable
{
IEnumerable<SomeDataType2> GetSomeData(string param);
void SaveData();
}
public class Service2: IService2
{
private MyContext context;
public Maestri(MyContext context)
{
this.context = context;
}
public void Dispose()
{
context.Dispose();
}
public IEnumerable<SomeDataType2> GetSomeData(string Param)
{
[...]
}
public void SaveData()
{
[...]
context.SaveChanges()
}
}
In Ninject CreateKernel are initialized like this:
kernel.Bind<MyContext>().ToSelf().InRequestScope();
kernel.Bind<IService1>().To<Service1>().InRequestScope();
kernel.Bind<IService2>().To<Service2>().InRequestScope();
In the controller:
public class MyController : Controller
{
private readonly IService1 _service1;
private readonly IService2 _service2;
public MyController(IService1 service1, IService2 service2)
{
_service1 = service1;
_service2 = service2;
}
public ActionResult SomeAction()
{
var data1 = _service1.GetSomeData("");
var data2 = _service2.GetSomeData("");
[...]
return View();
}
}
I've noticed that for every request to Controller/SomeAction the MyContext constructor has called only once, but the dispose() will be called twice. This leads me to think about a bad design of mine.
I've tried to remove the context.Dispose(); from the services, but this leads to MyContext.dispose to never get called, but a new instance is generated for every request.
Could someone please point me out what am I doing wrong?
Thanks!
Related
I am working on implementing the generic repository pattern with db Context and Autofac DI, and I am using the constructor based on dependency injections.
I have created the three layers repository pattern which are:
Infrastructure layer
Model layer
Services layer
Now, I am using this architecture in MVC web application when I try to pass the IContactService interface in ContactController and run the application.
I am getting the circular dependency detected error. Followings are my project code.
Repository code:
public class Repository<T> : IRepository<T> where T : class
{
private InvoiceBillingDbContext db;
private DbSet<T> dbSet;
public Repository()
{
db = new InvoiceBillingDbContext();
dbSet = db.Set<T>();
}
public IEnumerable<T> GetAll()
{
return dbSet.ToList();
}
public T GetById(object Id)
{
return dbSet.Find(Id);
}
public void Insert(T obj)
{
dbSet.Add(obj);
Save();
}
public void Update(T obj)
{
db.Entry(obj).State = EntityState.Modified;
Save();
}
public void Delete(object Id)
{
T getObjById = dbSet.Find(Id);
dbSet.Remove(getObjById);
}
public void Save()
{
db.SaveChanges();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (this.db != null)
{
this.db.Dispose();
this.db = null;
}
}
}
public void AddRange(List<T> obj)
{
dbSet.AddRange(obj);
Save();
}
public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
{
return dbSet.Where(predicate);
}
}
Interface IRepository
public interface IRepository<T> where T : class
{
IEnumerable<T> GetAll();
T GetById(object Id);
IEnumerable<T> Get(Expression<Func<T, bool>> predicate);
void Insert(T obj);
void AddRange(List<T> obj);
void Update(T obj);
void Delete(Object Id);
void Save();
}
My ContactRepository
public class ContactRepository:Repository<Contact>, IContactRepository
{
private IContactRepository _contractRepo;
public ContactRepository(IContactRepository contractRepo)
{
this._contractRepo = contractRepo;
}
}
My ContactRepository Interface
public interface IContactRepository:IRepository<Contact>
{
}
My Contact Service
public interface IContactService
{
void AddContact(Contact contact);
IEnumerable<Contact> GetContactsByTypeId(int typeId);
}
public class ContactService : IContactService
{
private readonly IContactRepository _contactRepository;
public ContactService(IContactRepository contactRepository)
{
this._contactRepository = contactRepository;
}
public void AddContact(Contact contact)
{
_contactRepository.Insert(contact);
}
public IEnumerable<Contact> GetContactsByTypeId(int typeId)
{
return _contactRepository.Get(i => i.TypeID == typeId);
}
}
My Controller
public class ContactController : Controller
{
// GET: Contact
private IContactService _contactService;
public ContactController(IContactService contactService)
{
this._contactService = contactService;
}
public ActionResult Index()
{
return View(new ContactViewModel());
}
public ActionResult AddContact(ContactViewModel contact)
{
if (ModelState.IsValid)
{
var _contactMapper = Mapper.Map<ContactViewModel, Contact>(contact);
_contactService.AddContact(_contactMapper);
ViewBag.Message = "Successfully Saved";
return View("Index",new ContactViewModel());
}
ViewBag.Message = "Error Occur Please try Again!";
return View("Index", new ContactViewModel());
}
}
And Autofac Dependency Injection
public static void ConfigureContainer()
{
var builder = new ContainerBuilder();
// Register all controllers in the Mvc Application assembly
builder.RegisterControllers(typeof(MvcApplication).Assembly);
// Registered Warehouse Reservoir Service
builder.RegisterType<InvoiceRepository>().As<IInvoiceRepository>();
// Registration Service Layer Service
builder.RegisterType<InvoiceService>().As<IInvoiceService>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
// Registered Warehouse Reservoir Service
builder.RegisterType<JournalVoucherRepository>().As<IJournalVoucherRepository>();
// Registration Service Layer Service
builder.RegisterType<JournalVoucherService>().As<IJournalVoucherService>();
// Registered Warehouse Reservoir Service
builder.RegisterType<ContactRepository>().As<IContactRepository>();
// Registration Service Layer Service
builder.RegisterType<ContactService>().As<IContactService>();
// Registration filter
builder.RegisterFilterProvider();
var container = builder.Build();
// Setting Dependency Injection Parser
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
You've only got one implementation of IContactRepository. You've also got a generic IRepository<T>.
Your implementation of IContactRepository gets another IContactRepository injected into it. So you're recursively resolving the same class and injecting it into itself.
public class ContactRepository:Repository<Contact>, IContactRepository
{
private IContactRepository _contractRepo;
// In order to resolve IContractRepository, the container has to
// resolve another IContractRepository to inject into it.
// And another one to inject into that. It's recursive.
public ContactRepository(IContactRepository contractRepo)
{
this._contractRepo = contractRepo;
}
}
Your example doesn't show how ContactRepository uses the IContactRepository that gets inject into it. But this
public interface IContactRepository:IRepository<Contact>
{
}
reveals that it's using the exact same methods found in IRepository<Contact>, because IContactRepository doesn't have any methods other than those.
So you most likely just need to modify ContactRepository to inject IRepository<Contact>, not IContactRepository.
public class ContactRepository:Repository<Contact>, IContactRepository
{
private IRepository<Contact> _contractRepo;
public ContactRepository(IRepository<Contact> contractRepo)
{
this._contractRepo = contractRepo;
}
}
That could be easy to overlook since both interfaces have exactly the same methods.
public class FooController : ApiController
{
private IDb db;
public FooController (IDb context)
{
db = context;
}
public void DoSomething(string value)
{
var output = new DoSomethingElse(value);
}
}
DoSomethingElse object is used by couple of methods in this class but it's not a requirement for all the methods. How do I register and resolve DoSomethingElse?
The problem as I understand it:
public class FooController : ApiController
{
private IDb db;
public FooController (IDb context)
{
db = context;
}
public void DoSomething(string value)
{
var output = new DoSomethingElse(value);
}
}
You don't want to instantiate the DoSomethingElse type everytime you instantiate the FooController. You also want to provide it with a value at run time.
So this calls for the Factory Pattern:
public interface IDoSomethingElseFactory
{
IDoSomethingElse Create(string value);
}
public class DoSomethingElseFactory : IDoSomethingElseFactory
{
public IDoSomethingElse Create(string value)
{
// Every call to this method will create a new instance
return new DoSomethingElse(value);
}
}
public class FooController : ApiController
{
private IDb db;
private readonly IDoSomethingElseFactory doSomethingElseFactory;
public FooController (
IDb context,
IDoSomethingElseFactory doSomethingElseFactory)
{
db = context;
this.doSomethingElseFactory = doSomethingElseFactory;
}
public void DoSomething(string value)
{
// this will be the point at which a brand new
// instance of `DoSomethingElse` will be created.
var output = doSomethingElseFactory.Create(value);
}
}
Then to register this:
builder.RegisterType<DoSomethingElseFactory>()
.As<IDoSomethingElseFactory>()
I have a problem for which lots of answers exist. The exception I've gotten says:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
As I've surfed the web and stack over flow pages, I've reached to this point that the instance of the DbContext should be only one in each UnitOfWork or the previous one must be detached. It sounds reasonable! But, my problem is that I have no idea where in my code (posted below) I have to place the modifications.
I've been trying to use Generic Repository and Unit of Work pattern plus EF code first approach.
public abstract class Repository<T> : IRepository<T> where T : BaseEntity
{
protected DbContext EntityContext;
protected readonly IDbSet<T> DbSet;
protected Repository(DbContext context)
{
EntityContext = context;
DbSet = context.Set<T>();
}
public virtual IEnumerable<T> GetList()
{
return DbSet.AsEnumerable();
}
public virtual T Add(T entity)
{
return DbSet.Add(entity);
}
}
The generic Unit of Work:
public sealed class UnitOfWork : IUnitOfWork
{
private DbContext _context;
public UnitOfWork(DbContext context)
{
_context = context;
}
public int Commit()
{
return _context.SaveChanges();
}
private void Dispose(bool disposing)
{
if (!disposing) return;
if (_context == null) return;
_context.Dispose();
_context = null;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
The client repository
public class ClientRepository : Repository<Client>, IClientRepository
{
public ClientRepository(DbContext context)
: base(context)
{
}
public override Client Add(Client entity)
{
return DbSet.Add(entity); // <-- Here the exception comes
}
}
This is the main part of the 'GenerateClients' method placed inside the 'DataGenerator' project.
var countries = container.Resolve<ICountryService>().GetList().ToList();
if (!countries.Any())
{
throw new InvalidDataGeneratorException(Strings.NoCountryToCreateClient);
}
var clientService = container.Resolve<IClientService>();
clientService.Create(new Client
{
Name = "Dell",
CountryId = countries[0].Id,
Country = countries[0],
AddressLineOne = "76-98 Victoria Street",});
And here the ClientService which uses the ClientRepository:
public class ClientService : Service<Client>, IClientService
{
IUnitOfWork UnitOfWork { get; set; }
private readonly IClientRepository _clientRepository;
private readonly ICalculatorService _calculatorService;
public ClientService(IClientRepository clientRepository,
IUnitOfWork unitOfWork,
ICalculatorService calculatorService)
: base(clientRepository, unitOfWork)
{
UnitOfWork = unitOfWork;
_calculatorService = calculatorService;
_clientRepository = clientRepository;
}
public override void Create(Client client)
{
_clientRepository.Add(client);
_clientRepository.Save();
}
}
Please note that some of the methods have been removed in order to minimize the length of the question.
Actually, when I run my Data Generator project which is of type Console, preceding to adding Clients, a number of Countries have been added with no problem, but as it comes to the Client service and it goes down into the ClientRepository, the exception raises up.
I don't know where should I place the modifications to avoid the exception. Many thanks
does Client have a relation to country and are you adding it as Client.Country = RELATED_COUNTRY perhaps it's trying to add the same country twice, I usually use Client.CountryId = ID_OF_COUNTRY
I am starting to use Ninject in my MVC5 code-first app. Here's my NinjectWebCommon.cs:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Bind<CMSContext>()
.ToSelf()
//.InSingletonScope();
.InRequestScope();
kernel.Bind<IExecutiveRepository>()
.To<ExecutiveRepository>();
kernel.Bind<IExecutiveSectionRepository>()
.To<ExecutiveSectionRepository>();
kernel.Bind<IExecutiveSectionMappingRepository>()
.To<ExecutiveSectionMappingRepository>();
kernel.Bind<IUserRepository>()
.To<UserRepository>();
kernel.Bind<IContentRepository>()
.To<ContentRepository>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
I tried .InSingletonScope() as well as .InRequestScope() but I still get the 'entity object cannot be referenced by multiple instances of IEntityChangeTracker' error.
Here is my Interface:
public interface IExecutiveRepository : IDisposable
{
IEnumerable<Executive> GetExecutives();
Executive GetExecutiveById(int executiveId);
void InsertExecutive(Executive executive);
void UpdateExecutive(Executive executive);
void DeleteExecutive(int executiveId);
void Save();
}
Here is my concrete:
public class ExecutiveRepository : IExecutiveRepository, IDisposable
{
private CMSContext context;
public ExecutiveRepository(CMSContext context)
{
this.context = context;
}
public IEnumerable<Executive> GetExecutives()
{
return context.Executives.ToList();
}
public Executive GetExecutiveById(int id)
{
return context.Executives.Find(id);
}
public void InsertExecutive(Executive executive)
{
context.Executives.Add(executive);
}
public void DeleteExecutive(int executiveId)
{
Executive executive = context.Executives.Find(executiveId);
context.Executives.Remove(executive);
}
public void UpdateExecutive(Executive executive)
{
context.Entry(executive).State = EntityState.Modified;
}
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);
}
}
Here is the controller(top pertinent part):
public class ExecutiveController : Controller
{
private IExecutiveRepository executiveRepository;
private IUserRepository userRepository;
private IExecutiveSectionRepository executiveSectionRepository;
private IExecutiveSectionMappingRepository executiveSectionMappingRepository;
private IContentRepository contentRepository;
private Ninject.IKernel _kernel = new StandardKernel();
//[Inject]
public ExecutiveController()
{
executiveRepository = _kernel.Get<ExecutiveRepository>();
userRepository = _kernel.Get<UserRepository>();
executiveSectionRepository = _kernel.Get<ExecutiveSectionRepository>();
executiveSectionMappingRepository = _kernel.Get<ExecutiveSectionMappingRepository>();
contentRepository = _kernel.Get<ContentRepository>();
}
...
Not sure what I am doing wrong but upon adding a new 'Executive' it bombs... I do understand it's trying to use separate contexts and that's the problem, but I 'm just not sure how to fix it. Apparently, the line in the NinjectWebCommon.cs class:
kernel.Bind<CMSContext>()
.ToSelf()
//.InSingletonScope();
.InRequestScope();
Is supposed to be the fix, but it isn't...
any ideas/suggestions?
You should be using NUGET package Ninject.Web.Mvc if you aren't already. This configures your application ready to use Ninject, other than your bindings. It looks like you are reasonably familiar with the bindings side of things already from what I can see in your CreateKernel() method.
Once your bindings are in place, you should not be creating Kernels in your controllers, this is because the Ninject.Web.Mvc library configures Ninject to create your controllers for you under the hood. Therefore any dependencies that you add to them should be automatically resolved.
So, you can use constructor injection to resolve your dependencies:
public class ExecutiveController : Controller
{
private IExecutiveRepository ExecutiveRepository;
private IUserRepository UserRepository;
private IExecutiveSectionRepository ExecutiveSectionRepository;
private IExecutiveSectionMappingRepository ExecutiveSectionMappingRepository;
private IContentRepository ContentRepository;
public ExecutiveController(
IExecutiveRepository executiveRepository,
IUserRepository userRepository,
IExecutiveSectionRepository executiveSectionRepository,
IExecutiveSectionMappingRepository executiveSectionMappingRepository,
IContentRepository contentRepository)
{
// Set the field values
this.ExecutiveRepository = executiveRepository,
this.UserRepository = userRepository,
this.ExecutiveSectionRepository = executiveSectionRepository,
this.ExecutiveSectionMappingRepository = executiveSectionMappingRepository,
this.ContentRepository = contentRepository;
}
public ActionResult Index(int id)
{
// Use one of your dependencies...
var executive = this.executiveRepository.GetExecutiveById(id);
}
}
Or you can use the [Inject] attribute which has the same effect:
public class ExecutiveController : Controller
{
[Inject]
public IExecutiveRepository executiveRepository { get; set; }
[Inject]
public IUserRepository userRepository { get; set; }
[Inject]
public IExecutiveSectionRepository executiveSectionRepository { get; set; }
[Inject]
public IExecutiveSectionMappingRepository executiveSectionMappingRepository { get; set; }
[Inject]
public IContentRepository contentRepository { get; set; }
public ExecutiveController()
{
}
public ActionResult Index(int id)
{
// Use one of your dependencies...
var executive = this.executiveRepository.GetExecutiveById(id);
}
}
You're creating a kernel per controller.
InRequestScope only ensures one instance per request per kernel.
So you need to adapt your setup of the kernel so there's only one kernel per web application. See:
Ninject.Web.Mvc
Tutorial
Youtube
This may not answer the question. But I tend to use the IDbContextFactory that EF provides you with and do something like this:
public interface IDefaultContextFactory : IDbContextFactory<CMSContext> {}
public class DefaultContextFactory : IDefaultContextFactory
{
private readonly Lazy<CMSContext> lazyContext = new Lazy<CMSContext>(() => new CMSContext());
public CMSContext Create()
{
return lazyContext.Value;
}
}
Then you just bind that, and when you need the context you can do something like this:
public class ExecutiveRepository : IExecutiveRepository, IDisposable
{
private readonly CMSContext context;
public ExecutiveRepository(IDefaultContextFactory contextFactory)
{
this.context = contextFactory.Create();
}
}
I believe #BatteryBackupUnit is correct, I would also consider using the above pattern for contexts.
I have implemented my first Generic repository in MVC app. Works fine but how to put repositories in Transaction scope?
public interface IRepository<TEntity> where TEntity : class
{
List<TEntity> FetchAll();
IQueryable<TEntity> Query { get; }
void Add(TEntity entity);
void Delete(TEntity entity);
void Save();
}
public class Repository<T> : IRepository<T> where T : class
{
private readonly DataContext _db;
public Repository(DataContext db)
{
_db = db;
}
#region IRepository<T> Members
public IQueryable<T> Query
{
get { return _db.GetTable<T>(); }
}
public List<T> FetchAll()
{
return Query.ToList();
}
public void Add(T entity)
{
_db.GetTable<T>().InsertOnSubmit(entity);
}
public void Delete(T entity)
{
_db.GetTable<T>().DeleteOnSubmit(entity);
}
public void Save()
{
_db.SubmitChanges();
}
#endregion
}
private void RegisterDependencyResolver()
{
var kernel = new StandardKernel();
var connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
kernel.Bind(typeof(DataContext)).ToMethod(context => new DataContext(connectionString));
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}
public class AdminController : Controller
{
private readonly IRepository<User> _userRepository;
private readonly IRepository<Order> _orderRepository;
public AdminController(IRepository<User> userRepository, IRepository<Order> orderRepository)
{
_userRepository = userRepository;
_orderRepository = orderRepository;
}
public ActionResult InsertUser(UserViewModel model)
{
//Skip Code
//Do not commit data to database if _orderRepository is failed to save data
_userRepository.Add(user);
_userRepository.Save();
//Skip Code
_orderRepository.Add(order);
_orderRepository.Save();
}
}
What would be best method to wrap repository code with Transaction scope in InsertUser action?
You are missing an abstraction here. You should place all your business logic inside command handlers and create a command handler decorator that implements transaction behavior. This article describes how to do this, but in short:
Define an ICommandHandler<TCommand> interface:
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
Create commands that define the contract of a business operation. Commands are simply DTOs (with only data and no behavior). For instance:
public class ShipOrderCommand
{
public int OrderId { get; set; }
public ShippingInfo Info { get; set; }
}
Implement command handlers that will contain the business logic / behavior for those commands:
public class ShipOrderCommandHandler
: ICommandHandler<ShipOrderCommand>
{
private readonly IRepository<Order> repository;
public ShipOrderCommandHandler(
IRepository<Order> repository)
{
this.repository = repository;
}
public void Handle(ShipOrderCommand command)
{
// do some useful stuf with the command and repository.
}
}
Let your MVC Controllers depend on the ICommandHandler<T> abstraction:
public ShipOrderController : Controller
{
private readonly ICommandHandler<ShipOrderCommand> handler;
public ShipOrderController(
ICommandHandler<ShipOrderCommand> handler)
{
this.handler = handler;
}
public void Ship(int orderId, ShippingInfo info)
{
this.handler.Handle(new ShipOrderCommand
{
OrderId = orderId,
Info = info
});
}
}
Define a generic decorator that implements transaction logic:
public TransactionalCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratedHandler;
public TransactionalCommandHandlerDecorator(
ICommandHandler<TCommand> decoratedHandler)
{
this.decoratedHandler = decoratedHandler;
}
public void Handle(TCommand command)
{
using (var scope = new TransactionScope())
{
this.decoratedHandler.Handle(command);
scope.Complete();
}
}
}
Ensure that each ShipOrderCommandHandler is decorated with a TransactionalCommandHandlerDecorator and injected into ShipOrderController. You can do this with your favorite DI container, or by hand:
protected override IController GetControllerInstance(
RequestContext requestContext, Type controllerType)
{
if (controllerType == typeof(ShipOrderController))
{
return new ShipOrderController(
new TransactionalCommandHandlerDecorator<ShipOrderCommand>(
new ShipOrderCommandHandler(
new OrderRepository())));
}
return base.GetControllerInstance(requestContext, controllerType);
}
With this in place you can run all your business logic inside a transaction, without the need for the business logic to be aware of that.
There's a pattern called Unit of work. Here's an explanation.