Using stored procedures for repository pattern with Service Class [duplicate] - c#

This question already has answers here:
How should I setup my repositories to use the same context?
(2 answers)
Closed 4 years ago.
Background
In my web application, I create stored procedures and then create an edmx file to use the stored procedures to handle all the database interaction.
But I started to wonder if I'm doing this right because, as you'll see in the example below,
I'm instantiating two instances of Context every time the Controller gets called even when the called method doesn't require database work
I'm instantiating an instances of Context in each repository, so when a request needs to get data from Repository A and B, I have two instances of Context.
Repository A
public class RepositoryA
{
private readonly Context _context;
public RepositoryA()
{
_context = new Context();
}
public List<CLASS> GetA(int id)
{
return _context.GetByID(id);
}
}
Repository B
public class RepositoryB
{
private readonly Context _context;
public RepositoryB()
{
_context = new Context();
}
public List<CLASS> GetB(int id)
{
return _context.GetByID(id);
}
}
Controller
public class Controller
{
private readonly IRepositoryA _reposA;
private readonly IRepositoryB _reposB;
public Controller() : this(new RepositoryA(), new RepositoryB())
{}
public Controller(IRepositoryA a, IRepositoryB b)
{
_respoA = a;
_reposB = b;
}
public ActionResult METHOD()
{
//do something with both RepositoryA and RepositoryB
var dataFromA = _reposA.GetA(ID);
var dataFromB = _reposB.GetB(ID);
return View(someData);
}
}
Now the question is: I'm not sure if this is supposed to be the normal implementation, so I've been trying to figure out how I can set this up in more efficient and testable way, and I tried something like this.
I believe that this design solves some of my concerns:
Service gets called every time Controller gets called, but Context doesn't get instantiated every time (Context gets instantiated per request).
When a service requires both Repository A and B, it uses the same Context
However, with how Service is set up, I can't unit test Service with test data because I can't use my mock repositories.
public class Controller
{
private Service _service;
public Controller()
{
_service = new Service();
}
public ActionResult METHOD()
{
_service.DoSomethingWithRepoAandB();
return View();
}
}
public class Service
{
public void DoSomethingWithRepoAandB()
{
using (var _context = new Context())
{
RepositoryA a = new RepositoryA(_context);
RepositoryB b = new RepositoryB(_context);
something = a.DoSomethingWithA();
otherThing = b.DoOtherThingWithB();
}
}
}
So, I'm thinking I should set up Service like this.
With this design, Context will be instantiated every time Controller gets called (unless I instantiate Service in a Controller method), but I can unit test by passing mock repositories.
public class Service
{
private readonly Context _context;
private IRepositoryA _a;
private IRepositoryB _b;
public Service()
{
_context = new Context();
_a = new RepositoryA(_context);
_b = new RepositoryB(_context);
}
// Pass Mock Repositories in unit tests
public Service(RepositoryA a, RepositoryB b)
{
_a = a;
_b = b;
}
public void DoSomethingWithRepoAandB()
{
something = _a.DoSomethingWithA();
otherThing =_b.DoOtherThingWithB();
}
}
Am I doing this completely wrong or on the ok track? I'd appreciate any advice.

Your services should NOT have any information about your context, that information should only be accessible by the repository, following SOLID principles.
The access of your layers should be as follows:
Controller -> Service -> Repository -> Context
On your IRepository interfaces, you will have the methods you're going to call, and you either instantiate them manually, but to implement it correctly, you'll have to setup your dependency injection.
Also, your Repositories constructors dont receive any context as a parameter, so you cant do something like this:
RepositoryA a = new RepositoryA(_context);
On another point, your controller shouldn't access repositories as well, as it breaks your architecture
public ActionResult METHOD()
{
//do something with both RepositoryA and RepositoryB
var dataFromA = _reposA.GetA(ID);
var dataFromB = _reposB.GetB(ID);
return View(someData);
}
Here's the correct code, for further understanding:
public class RepositoryA : IRepositoryA
{
private readonly Context _context;
public RepositoryA(Context context)
{
_context = context;
}
public List<CLASS> GetA(int id)
{
return _context.GetByID(id);
}
}
public interface IRepositoryA
{
List<CLASS> GetA(int id);
}
public class RepositoryB : IRepositoryB
{
private readonly Context _context;
public RepositoryB(Context context)
{
_context = context;
}
public List<CLASS> GetB(int id)
{
return _context.GetByID(id);
}
}
public interface IRepositoryB
{
List<CLASS> GetB(int id);
}
public class Controller
{
private IService _service;
public Controller(IService service)
{
_service = service;
}
public ActionResult METHOD(int id)
{
//do something with both RepositoryA and RepositoryB THROUGH the service. The service needs to hold the business rules, and repositories should only care about querying data and handling contexts.
var data = _service.DoSomethingWithRepoAandB(id)
return View(data);
}
}
public class Service : IService
{
private IRepositoryA _a;
private IRepositoryB _b;
// Pass Mock Repositories in unit tests -> PS: You can't have 2 constructors if you're using dependency injection.
public Service(RepositoryA a, RepositoryB b)
{
_a = a;
_b = b;
}
public void DoSomethingWithRepoAandB(int id)
{
var something = _a.GetA(id);
var otherThing = _b.GetB(id);
}
}
public interface IService
{
void DoSomethingWithRepoAandB(int id);
}
public class Bootstrapper
{
//this class should be in a separated assembly, responsible for handling the dependency injection. Using Simple Injection syntax just as an example
public static void RegisterServices(Container container) //IoC Container
{
container.Register<IService, Service>(Lifestyle.Scoped);
container.Register<IRepositoryA, RepositoryA>(Lifestyle.Scoped);
container.Register<IRepositoryB, RepositoryB>(Lifestyle.Scoped);
container.Register<Context>(() => {
var options = // Configure your ContextOptions here
return new Context(options);
});
}
}
public class Startup
{
//This is your startup configuration if you're using WebApi. If you're on MVC, you can do this on your Global.asax
public void Configuration()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
BootStrapper.RegisterServices(container);
}
}

Related

Dependency Injection containers - how do I get a specific instance of an object?

For example, I have a Repository class for getting data from a database, and there are several service classes, let's say Service1, Service2, Service3.
I will have multiple Repository instances, for example, for two or three databases. And, you should be able to configure services to work with a specific database.
I can't figure out how to implement these dependencies using the Dependency Injection container.
As far as I understand, I can register the Repository service either as a Singleton, or a new instance will be created for each dependency.
But, I only need two repositories, Repository ("DB1") and Repository ("DB2"), and when creating a service instance, I should be able to choose which database to work with. That is, as an option-Service1(Repository ("DB1")), Service2 (Repository ("DB1")), Service1 (Repository ("DB2")).
For example:
public class Program
{
static void Main()
{
var connectionStringDb1 = "DB1 connection string";
var connectionStringDb2 = "DB2 connection string";
var repositoryDb1 = new Repository(connectionStringDb1);
var repositoryDb2 = new Repository(connectionStringDb2);
var smsSendService1 = new SmsSendService(repositoryDb1);
var smsSendService2 = new SmsSendService(repositoryDb2);
var emailSendService1 = new EmailSendService(repositoryDb1);
smsSendService1.Run();
var tasks = new Task[]
{
smsSendService1.Run(),
smsSendService2.Run(),
emailSendService1.Run()
};
Task.WaitAll(tasks);
}
}
public class Repository
{
private string _connectionString;
public Repository(string connectionString)
{
_connectionString = connectionString;
}
public object GetData()
{
// Getting data from the Database
var data = ...;
return data;
}
}
public class SmsSendService
{
private readonly Repository _repository;
public SmsSendService(Repository repository)
{
_repository = repository;
}
public Task Run()
{
return Task.Run(() =>
{
// Sending SMS in a loop
while (true)
{
var data = _repository.GetData();
// ...
Task.Delay(1000);
}
});
}
}
public class EmailSendService
{
private readonly Repository _repository;
public EmailSendService(Repository repository)
{
_repository = repository;
}
public Task Run()
{
return Task.Run(() =>
{
// Sending Email in a loop
while (true)
{
var data = _repository.GetData();
// ...
Task.Delay(1000);
}
});
}
}
Try to take a look at autofac named instances

unity resolve instance at web api controller

Is there any way to resolve the instance of a class at the controller level? I would like to override the previous instance created by unity and assign this new value via the controller.
Problem is I am not sure how to access the unity container in the web app controller.
Here is my code:
Repository:
public class UserRepository: IUserRepository
{
private UserInformation _userInfo;
public UserRepository(string headerValue)
{
_userInfo = LoadUserData(headerValue);
}
public UserInformation GetUserInfo()
{
return _userInfo;
}
}
public class UserInformation
{
public string FirstName;
public string LastName;
}
Unity Configuration:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//Some code omitted
config.DependencyResolver = new UnityDependencyResolver(UnityConfig.RegisterComponents());
}
}
public static class UnityConfig
{
public static UnityContainer RegisterComponents()
{
//Unity Configuration
var container = new UnityContainer();
container.RegisterType<IUserRepository, UserRepository>(new InjectionConstructor("DummyHeaderValue"));
return container;
}
}
Controller:
public class CustomerController : ApiController
{
public CustomerController()
{
//Something like this
container.Resolve<UserRepository>(new InjectionConstructor(Request.GetHeader("RealHeaderValueFromHttpRequest")));
}
}
Then I should be able to use the updated UserRepository instance throughout the application.
Any thoughts on how to achieve this?
Edit: As pointed out by #Nkosi I don't have access to Request in controller constructor. So let me rephrase my question again:
How would I initialise UserRepository with UserInformation object which contains details about the current user? The reason I want to do this is that throughout my application I want user details and I don't want to pass User Id from each method
Something like this: From any method throughout application
UserInformation obj = _userRepository().GetUserInfo();
Create an abstraction to get access to the request
public interface IHeaderService {
string RealHeaderValueFromHttpRequest();
}
Its Implementation will have access to the context and request to get the desired functionality
public class HeaderService : IHeaderService {
public string RealHeaderValueFromHttpRequest() {
return HttpContext.Current.Request.Headers["RealHeaderValueFromHttpRequest"];
}
}
The service will now be explicitly injected into the dependent repository
public class UserRepository: IUserRepository {
private readonly IHeaderService headerService;
public UserRepository(IHeaderService headerService) {
this.headerService = headerService;
}
public UserInformation GetUserInfo() {
var headerValue = headerService.RealHeaderValueFromHttpRequest();
var _userInfo = LoadUserData(headerValue);
return _userInfo;
}
//...
}
The repository will then also be explicitly injected into dependent controllers.
public class CustomerController : ApiController {
private readonly IUserRepository repositoty;
public CustomerController(IUserRepository repositoty) {
this.repository = repository;
}
public IHttpActionResult SomeAction() {
//NOTE: Only access user info in a controller action
var userInfo = repository.GetUserInfo();
//... use user info.
}
//...
}
Now all that is left is to make sure all abstractions and their implementations are registered with the dependency container
public static class UnityConfig {
public static UnityContainer RegisterComponents() {
//Unity Configuration
var container = new UnityContainer();
container.RegisterType<IUserRepository, UserRepository>();
container.RegisterType<IHeaderService, HeaderService>();
return container;
}
}

ServiceStack testing methods that works with EF

As an answer to my own question:
What would be the most elegant way to use Entity Framework with Generic Repository, in Service Stack, and to write Integration \ Unit Tests for service?
At the moment, this is how my structure looks like:
Generic repository layer:
public class GenericRepository<TEntity> where TEntity : class
{
internal DbContext Context;
//...
//CRUD Operations, etc.
}
Unit of work layer:
public class UnitOfWork : IDisposable
{
private readonly DbContext _context;
public UnitOfWork(DbContext ctx)
{
_context = ctx;
}
private bool _disposed;
private GenericRepository<User> _userRepository;
public GenericRepository<User> UserRepository
{
get { return _userRepository ?? (_userRepository = new GenericRepository<User>(_context)); }
}
//...
}
Business layer:
public class UserBusiness
{
public UnitOfWork UoW { get; set; }
public void AddUser(Models.User user)
{
//Map from domain model to entity model
var u = Mapper.Map<Models.User, DAL.Repository.User>(user);
UoW.UserRepository.Insert(u);
UoW.Save();
}
}
API project:
public class AppHost : AppHostBase
{
public AppHost() : base("Users Service", typeof(UsersService).Assembly) { }
//...
public override void Configure(Funq.Container container)
{
//...other configuration
//UoW registration
container.Register(c => new UnitOfWork(new DbContext("my-DB-connection"))).ReusedWithin(Funq.ReuseScope.Hierarchy);
//Business layer class registration
container.Register<UserBusiness>(c=>new UserBusiness {
UoW = c.Resolve<UnitOfWork>()
}).ReuseWithin(Funq.ReuseScope.Hierarchy);
}
}
public class UsersService : Service
{
public UserBusiness UB { get; set; }
public object Post(User u)
{
UB.AddUser(u);
//...
}
}
So when it comes to integration testing, I can just do something like this:
Declare _appHost
private ServiceStackHost _appHost;
And configure funq container like this:
public override void Configure(Funq.Container container)
{
//...create mocked context
var mockedContext = new Mock<IDbContext>();
mockedContext.Setup(x => x.Set<User>()).Returns(new List<User>
{
new User { ID = 1, FirstName = "John", LastName = "Doe" }
});
//(or use effort or any other way to create it)
container.Register(c => new UnitOfWork(mockedContext)).ReusedWithin(Funq.ReuseScope.Hierarchy);
}
And test as usual:
[Test]
public void Get_User_By_Id()
{
//...generate client instance (JsonServiceClient) etc.
var customer = client.Get(new GetCustomer { Id = 1 });
Assert.AreEqual("John", customer.FirstName);
///...
}
In addition to have all layers available for DI, and mocking, I also created IDbContext, IGenericRepository, IUnitOfWork, etc. interfaces.
I didn't include it here in order to keep this as simple as I could.
But I would like to hear if there's a better (more elegant way) to do it.

Ninject: entity object cannot be referenced by multiple instances of IEntityChangeTracker

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.

How do you unit test a MVC controller with EF SaveChanges

Below is a controller with a Post Method. How do i write a unit-test against the CREATE method without saving the changes to the database?
I am trying to write test against my controllers so that when other developers change the code it will not break my functionality ( i have a little bit of functionality on the Create method to keep it simple for now).
public class AdministratorController : Controller
{
private IUnitOfWork _uow;
[HttpPost]
public ActionResult Create(MyModel model)
{
ViewBag.id = model.Id;
if (model.FirstName == model.LastName)
{
ModelState.AddModelError("", "Cannot have same first name and last name.");
}
if (ModelState.IsValid)
{
MyClass record = new MyClass();
record.SAFirstName = model.FirstName;
record.SALastName = model.LastName;
record.SATitle = model.Title;
record.SAEmail = model.EmailAddress;
record.Since = DateTime.Now;
_uow.AdministratorRepository.AddRecord(record);
_uow.SaveChanges();
return RedirectToAction("Index", "Administrator");
}
return View(model);
}
}
2.) my UOW looks something like this:
public class UnitOfWork : IUnitOfWork
{
private readonly MasterContext _context;
public UnitOfWork(MasterContext context)
{
_context = context;
}
public UnitOfWork()
{
_context = new MasterContext();
}
public void SaveChanges()
{
_context.SaveChanges();
}
private IAdministratorRepository _Repo;
public IAdministratorRepository AdministratorRepository
{
get
{
if (this._Repo == null)
{
this._Repo = new IAdministratorRepository(_context);
}
return _Repo;
}
}
3) And my AdministratorRepository constructor looks like:
private readonly MasterContext _context;
public AdministratorRepository(MasterContext context)
{
_context = context;
}
You need to be able to inject a fake/mock IUnitOfWork into your controller. The simplest way to do that is to create an internal constructor on the controller that takes the fake object and create a property that either creates a new instance or returns the existing one.
private IUnitOfWork _uow;
private IUnitOfWork UnitOfWork
{
get
{
_uow = _uow ?? new UnitOfWork();
return _uow;
}
}
public AdministratorController() {}
internal AdministratorController( IUnitOfWork uow )
{
_uow = uow;
}
You'll also need to modify the AssemblyInfo file for the MVC project to make the internal constructor visible to the unit test project. Look up the InternalsVisibleToAttribute for that.
Now in the unit test you can create your fake/mock object and inject it. You don't indicate what mocking framework you're using. We use FakeItEasy, so it would be something like:
var uow = A.Fake<IUnitOfWork>();
var controller = new AdministratorController( uow );
A.CallTo( () => uow.SaveChanges() ).MustHaveHappened();
You should mock your dependencies.In your example AddRecord() of your repository.And after that you should test the returning model fields with your expected model(that you have to set in your unit testing method).

Categories