ServiceStack testing methods that works with EF - c#

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.

Related

Unit of Work and Repository Pattern in MVC controller constructor injection using Unity not doing any changes to database

1.) I am a building new MVC application with 3 tier project architecture having:
Common Project with entities
Business/Service holding interfaces and logic classes and
Data holding repositories, interfaces, DbContext and UnitOfWorkclasses. I am using Unity Config to register dependencies, DbContext and UnitOfWork.
2.) I created a repository for each table and one generic repository that does basic CRUD operations.
Example Entity residing in Common Project:
public class MenuSecd
{
[Key, Column(Order = 0)]
public string prg_module { get; set; }
[Key, Column(Order = 1)]
public int prg_numb { get; set; }
[Key, Column(Order = 2)]
public string menu_level { get; set; }
}
My generic Entity Logic Interface residing in Business Project:
public interface IEntityLogic<T> : ILogic where T : class
{
void Create(T entity);
void Delete(T entity);
IEnumerable<T> GetAll();
void Update(T entity);
}
Entity Logic Class:
public abstract class EntityLogic<T> : IEntityLogic<T> where T : class
{
IUnitOfWork _unitOfWork;
IGenericRepository<T> _repository;
public EntityLogic(IUnitOfWork unitOfWork, IGenericRepository<T> repository)
{
_unitOfWork = unitOfWork;
_repository = repository;
}
public virtual void Create(T entity)
{
if(entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
_repository.Add(entity);
_unitOfWork.Commit();
}
}
Example Business Logic class for the entity defined in Common Project:
public class MenuSecdLogic : EntityLogic<MenuSecd>, IMenuSecdLogic
{
IUnitOfWork _unitOfWork;
IMenuSecdRepository _repository;
public MenuSecdLogic(IUnitOfWork unitOfWork, IMenuSecdRepository repository) : base(unitOfWork, repository)
{
_unitOfWork = unitOfWork;
_repository = repository;
}
public List<MenuSecd> GetItems(string usrgrp_id)
{
return _repository.GetItems(usrgrp_id);
}
}
My Generic Repository in Data Project looks like:
public abstract class GenericRepository<T> : IGenericRepository<T> where T : class
{
protected DbContext _entities;
protected readonly IDbSet<T> _dbset;
public GenericRepository(DbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public virtual T Add(T entity)
{
return _dbset.Add(entity);
}
public virtual T Delete(T entity)
{
return _dbset.Remove(entity);
}
public virtual void Edit(T entity)
{
_entities.Entry(entity).State = EntityState.Modified;
}
}
Repository Interface for the same Entity is defined as:
public interface IMenuSecdRepository : IGenericRepository<MenuSecd>
{
List<MenuSecd> GetItems(string usrgrp_id);
}
Repository class for above mentioned interface is:
public class MenuSecdRepository : GenericRepository<MenuSecd>, IMenuSecdRepository
{
public MenuSecdRepository(DbContext context) : base(context)
{
}
public List<MenuSecd> GetItems(string usrgrp_id)
{
return _dbset.Where(m => m.usrgrp_id == usrgrp_id).ToList();
}
}
My DbContext looks like:
public class DashboardContext : DbContext
{
public DashboardContext() : base("Name=DBEntities")
{
}
public DbSet<MenuSecd> menusecd { get; set; }
public override int SaveChanges()
{
var modifiedEntries = ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified);
//future custom implementation like auditing
return base.SaveChanges();
}
}
My UnitOfWork looks like:
public sealed class UnitOfWork : IUnitOfWork
{
private DbContext _dbContext;
public UnitOfWork(DbContext context)
{
_dbContext = context;
}
public int Commit()
{
return _dbContext.SaveChanges();
}
//disposes current object
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
//disposes all external resources
private void Dispose(bool disposing)
{
if (disposing)
{
if (_dbContext != null)
{
_dbContext.Dispose();
_dbContext = null;
}
}
}
}
My controller:
public class DashController : Controller
{
private readonly IMenuSecdLogic _menuSecdLogic;
public DashController(IMenuSecdLogic menuSecdLogic)
{
_menuSecdLogic = menuSecdLogic;
}
public void Save()
{
var menuSecd = new menuSecd();
//populate all fields for entity MenuSecd
_menuSecdLogic.Create(menuSecd);
}
}
My Unity Config in App_Start looks like :
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<DbContext, DashboardContext>();
container.RegisterType<IUnitOfWork, UnitOfWork>();
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<>));
container.RegisterType<IMenuSecdLogic, MenuSecdLogic>();
container.RegisterType<IMenuSecdRepository, MenuSecdRepository>();
}
So when run above project everything builds fine. But when controller calls:
_menuSecdLogic.Create(menuSecd);
It reaches Entity Logic and adds a new entity to _repository at :
_repository.Add(entity);
_unitOfWork.Commit();
But when it hits next line to actually save it to database which is :
return _dbContext.SaveChanges();
in UnitOfWork.cs file.
It comes to dashboardContext where it finally have to save it to database. But it does execute :
var modifiedEntries = ChangeTracker.Entries().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified);
return base.SaveChanges();
But nothing changes in database. There will be no record in database. To test I have added modifiedEntries to see if it is in context or not. By the time control reaches this point I see no modified entries at all. But in EntityLogic.cs it does add a new entity to local entities in repository.
I am not sure what is happening with UnitOfWork here. I ran SQL Profiler to see if it is hitting database or not. Interestingly it is not hitting database at all. But if my make following changes to EntityLogic like this:
public virtual void Create(T entity)
{
if(entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
_repository.Add(entity);
_repository.Save();
//_unitOfWork.Commit();
}
It hits Database and records gets saved fine. But I am not getting why it is neither tracking changes nor hitting database if I use _unitOfWork.Commit() which I want to do. Please help.
It looks like your issue is the scope of your DbContext. Your UnitOfWork and GenericRepository<T> classes are getting different instances.
Not super familiar with Unity, but it looks like you want to use something like this for your DbContext registration:
container.RegisterType<DbContext, DashboadContext>(new PerRequestLifetimeManager());
This will create a single DashboardContext for each request, and your UnitOfWork and GenericRepository<T> classes will be working within the same context.

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

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);
}
}

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 to mock Entity Framework 6 Async methods?

I am new in mocking. I want to mock up my base repository which is depend on Entity Framework 6 DbContext But I fail. I searched in Google a lot but did not get any sufficient result. At last I got an example at testing with async queries and try to follow but it is worked for me.
Here is my code :
DbContext :
public class TimeSketchContext : DbContext
{
public virtual DbSet<EmployeeSkill> EmployeeSkill { get; set; }
}
Base Repository :
public class BaseRepository<T> : IRepositoryBase<T> where T : class, IEntity, new()
{
protected readonly DbContext InnerDbContext;
protected DbSet<T> InnerDbSet;
public BaseRepository(DbContext innerDbContext)
{
InnerDbContext = innerDbContext;
InnerDbSet = InnerDbContext.Set<T>();
}
public virtual Task<T> FindAsync(long id)
{
return InnerDbSet.FirstOrDefaultAsync(x=>x.Id == id);
}
}
Test :
[Fact]
public async Task DbTest()
{
var dummyData = GetEmployeeSkills();
var mockSet = new Mock<DbSet<EmployeeSkill>>();
mockSet.As<IDbAsyncEnumerable<EmployeeSkill>>()
.Setup(x => x.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<EmployeeSkill>(dummyData.GetEnumerator()));
mockSet.As<IQueryable<EmployeeSkill>>()
.Setup(x => x.Provider)
.Returns(new TestDbAsyncQueryProvider<EmployeeSkill>(dummyData.Provider));
mockSet.As<IQueryable<EmployeeSkill>>().Setup(m => m.Expression).Returns(dummyData.Expression);
mockSet.As<IQueryable<EmployeeSkill>>().Setup(m => m.ElementType).Returns(dummyData.ElementType);
mockSet.As<IQueryable<EmployeeSkill>>().Setup(m => m.GetEnumerator()).Returns(dummyData.GetEnumerator());
var mockContext = new Mock<TimeSketchContext>();
mockContext.Setup(c => c.EmployeeSkill).Returns(mockSet.Object);
var baseRepository = new BaseRepository<EmployeeSkill>(mockContext.Object);
var data = await baseRepository.FindAsync(1);
Assert.NotEqual(null, data);
}
private EmployeeSkill GetEmployeeSkill()
{
return new EmployeeSkill
{
SkillDescription = "SkillDescription",
SkillName = "SkillName",
Id = 1
};
}
private IQueryable<EmployeeSkill> GetEmployeeSkills()
{
return new List<EmployeeSkill>
{
GetEmployeeSkill(),
GetEmployeeSkill(),
GetEmployeeSkill(),
}.AsQueryable();
}
Result is :
Assert.NotEqual() Failure
I think problem is
public BaseRepository(DbContext innerDbContext)
{
InnerDbContext = innerDbContext;
InnerDbSet = InnerDbContext.Set<T>(); <<<<<<<<<<<
}
But don`t understand why and how to solve this.
I am using :
Visual Studio 2013 Ultimate
Moq
xUnit
Thank`s in advance.
You are right the problem is in your InnerDbContext.Set<T>(); statement.
In the current version of the EF (6.0.2) the DbContext.Set<T> method is not virtual so it cannot be mocked with Moq.
So you cannot easily make your test pass except by changing your design of the BaseRepository to not depend on the whole DbContext but on one DbSet<T>:
So something like:
public BaseRepository(DbSet<T> dbSet)
{
InnerDbSet = dbSet;
}
Then you can pass directly in your mocked DbSet.
Or you can create a wrapper interface for DbContext:
public interface IDbContext
{
DbSet<T> Set<T>() where T : class;
}
public class TimeSketchContext : DbContext, IDbContext
{
public virtual DbSet<EmployeeSkill> EmployeeSkill { get; set; }
}
Then use IDbContext in your BaseRepository:
public class BaseRepository<T> : IRepositoryBase<T> where T : class, IEntity, new()
{
protected readonly IDbContext InnerDbContext;
protected DbSet<T> InnerDbSet;
public BaseRepository(IDbContext innerDbContext)
{
InnerDbContext = innerDbContext;
InnerDbSet = InnerDbContext.Set<T>();
}
public virtual Task<T> FindAsync(long id)
{
return InnerDbSet.FirstOrDefaultAsync(x => x.Id == id);
}
}
And finally you just need to change two lines in your test to make it pass:
var mockContext = new Mock<IDbContext>();
mockContext.Setup(c => c.Set<EmployeeSkill>()).Returns(mockSet.Object);

Generic Repository and Transaction

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.

Categories