Unit of work pattern not allowing me to create db context without options - asp.net

I am using ef core and I am trying to implement the repository pattern as part of best practices. But I am we bit confused on the context normally I would create the context in the and inject
HomeController(WarehouseDBContext _context)
I have created my unitOfWork Class as suggested by the docs here
https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application#creating-the-unit-of-work-class
However I am tad confused. It's expecting options here which is normally handled on the controller.
My UnitOfWork class
public class WarehouseUnitOfWork : IDisposable
{
private WarehouseDBContext context = new WarehouseDBContext();
private WarehouseRepository<StockItem> stockRepository;
public WarehouseRepository<StockItem> StockRepoistry
{
get
{
if (this.stockRepository == null)
{
this.stockRepository = new WarehouseRepository<StockItem>(context);
}
return stockRepository;
}
}
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);
}
}
But here it is complain that it expect options which would I presume contain the connection string. I am trying to decouple my code from EF so that If I want to upgrade in the future will be easier. My WareshouseDBContext is describe below
As you can see it is expecting options. What should I pass through here?
namespace WareHouseDal.Dal {
public class WarehouseDBContext : IdentityDbContext<ApplicationUser> {
public WarehouseDBContext(DbContextOptions<WarehouseDBContext> options)
: base(options) {
}
public DbSet<WarehouseCrm> Warehouse { get; set; }
public DbSet<Company> Companies { get; set; }
}
}
When I used to create my context before I just used the singleton pattern of
private readonly WarehouseDBContext _context;
Is their something else I need to do to allow it to accept the creation of the context on the unit of work level.
Error being given is

You shouldn't create a DbContext manually. Why not injecting the DbContext in your UOW class? Then the DI will manage the life cycle of the db context. To be honest I am not a fan of adding a UOW wrapper around EF which already implements the UOW pattern.
I would recommend you to see both talks, it will change the way you structure apps forever:
https://www.youtube.com/watch?v=5OtUm1BLmG0&ab_channel=NDCConferences
https://www.youtube.com/watch?v=5kOzZz2vj2o&t=3s&ab_channel=NDCConferences
Another amazing talk about EF Core details: https://www.youtube.com/watch?v=zySHbwl5IeU&ab_channel=NDCConferences
If you want to stick with Repository pattern, please check Ardalis repository with a clear example: https://github.com/ardalis/CleanArchitecture

I agree Ardalis repository is a great tutorial/example, in case if anyone want a lite solution to implement the Repository and Unit of Work Patterns in EF 5/EF 6.
you may check out the below one, I tested it would work in EF Core 6
https://pradeepl.com/blog/repository-and-unit-of-work-pattern-asp-net-core-3-1/

Related

Unit of Work with Repository having Generic methods

We are using EF with DB first, and we are not planning to create Repository classes per table. Instead, we will have repository classes representing modules, which internally might interact with multiple tables.
The code which I have started writing is something like this:
public class ModuleRepository
{
public void GetModules()
{
using (IUnitOfWork uow = new UnitOfWork())
{
//Get the specific DBSet
var dbTable = uow.GetDbSet<Customer>();
var dbTable1 = uow.GetDbSet<Supplier>();
//do whatever you want to do.
//call save changes to commit
uow.SaveChanges();
}
}
}
class UnitOfWork: IUnitOfWork
{
private DbContext _context;
public UnitOfWork()
{
_context = new DbContext("");
}
public void Dispose()
{
throw new NotImplementedException();
}
public void SaveChanges()
{
throw new NotImplementedException();
}
public DbSet<T> GetDbSet<T>() where T:class
{
DbSet<T> entities = _context.Set<T>();
return entities;
}
}
public interface IUnitOfWork: IDisposable
{
void SaveChanges();
DbSet<T> GetDbSet<T>() where T : class;
}
In SaveChanges I will have the _context.SaveChanges() to commit the changes to the DB.
This is I guess one way to do this.
Another possible way could be:
create a generic base repository class. Each module repository will have a list of these repository classes.
uow class
UOW Manager -> will pass list of base repositories to say a method Setup. This UOW Manager will create a UOW with a context, and this UOW will be passed to each repository - effectively all repository having the same context.
I think code wise it will work, though not sure which one is the right approach or there could be some better approach.
Also in any of these two scenarios, how to achieve unit testing? Any ideas around this?

What are best practices for managing DataContext?

In an effort to make my entities persistent ignorant and make my repositories testable, I've implemented a repository pattern like so:
public interface IJobRepository : IRepository<Job>
{
Job GetJobById(int jobId); //Special case where I'm eager loading other entities
void SaveJob(Job job, Job originalJob);
}
public class JobRepository : IJobRepository
{
private readonly IContext _context;
public JobRepository()
{
_context = new CustomObjectContext();
}
public JobRepository(UnitOfWork unitOfWork)
{
_context = unitOfWork.Context;
}
//Basic GetAll, GetById, Add and Delete methods from IRepository<T> Interface here
//omitted for brevity
public Job GetJobById(int jobId)
{
var job = _context.Jobs.Include("Company").Include("Location").
Include("PlantInfo").Where(j => j.Jobid == jobId).SingleOrDefault();
_context.DisposeContext();
return job;
}
public void SaveJob(Job job, Job originalJob)
{
if (job.Jobid > 0)
{
// Update
_context.Jobs.Attach(originalJob);
_context.PlantInfoes.Attach(originalJob.PlantInfo);
_context.Jobs.ApplyCurrentValues(job);
_context.PlantInfoes.ApplyCurrentValues(job.PlantInfo);
Note: ApplyCurrentValues is an extension method I'm using on the ObjectSet
}
else
{
// Create
_context.Jobs.AddObject(job);
}
_context.Save();
}
}
public class UnitOfWork
{
private readonly IContext _context;
public UnitOfWork()
{
_context = new CustomObjectContext();
}
public UnitOfWork(IContext context)
{
_context = context;
}
public string Save()
{
return _context.Save();
}
internal IContext Context
{
get { return _context; }
}
}
public interface IContext
{
IObjectSet<Job> Jobs { get; }
IObjectSet<Company> Companies { get; }
IObjectSet<Location> Locations { get; }
IObjectSet<PlantInfo> PlantInfoes { get; }
string Save();
}
My ObjectContext inherits from IContext...So my understanding is that I will only use the overloaded constructor on the repository to facilitate unit tests or to use it in the case that I want to use the same context (not desirable based on this post I found on SO "Entity Framework and Connection Pooling" -- Is this right?
Also, assuming the context only gets disposed when the repository is garbage collected, I have to dispose the context explicitly to avoid the "An entity object cannot be referenced by multiple instances of IEntityChangeTracker." exception when attaching the entity prior to a save.
That said, what is the best practice for managing the DataContext in a manner that keeps your entities persistent ignorant and repositories testable?
Note: This is an asp.net webapplication; UnitOfWork and IContext implementation was based on examples from "Programming Entity Framework", Second Edition by Julia Lerman Ch24.
Thanks in advance!
Firstly, I would ensure that whatever my "consumable" object is (either repository or unit of work, depending on your setup) implements IDisposable. When your consumbed object is disposed of, then you would dispose your underlying context.
For instance, if you're using your UnitOfWork as the consumable object (the one that gets created and called in your application), it would look something like:
public class UnitOfWork : IDisposable
{
// All the other stuff you had before plus:
public void Dispose ()
{
if (_context != null)
{
_context.Dispose ();
}
}
}
(Note: This can also be done on your repositories if they're the ones being consumed directly)
And then, you have a few options in your application. If you are going to use the UnitOfWork directly, you can use it like:
public void SomeMethodThatAccessesYourData ()
{
using (var unitOfWork = new UnitOfWork (/*Load in the context*/))
{
// Access your data here.
}
}
Or, in your Web Forms or MVC object you can use constructor injection and dispose of it when the Web Forms or MVC object is disposed of:
// If you're using MVC:
public class MyController : Controller
{
private UnitOfWork _unitOfWork;
public MyController (UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public override Dispose (bool Disposing)
{
if (Disposing && _unitOfWork != null)
{
_unitOfWork.Dispose ();
}
}
}
The same idea stands for a web forms Page.
The main reason for using the constructor overload is for Inversion of Control (IOC). It helps with both unit testing and with production code when used with an IoC Container. WebForms doesn't lend itself well to IoC, but it is really easy with MVC.
Edit
I don't really see the connection with your repositories and the unit of work. Usually you access the repositories from a unit of work or, in other implementations, you request a unit of work from your target repository. In your implementation (which I understand is not your own) there seems to be no need for both.
Edit 2
If the UoW is overkill for your application, and you know you can use IoC to inject your IContext, and you don't have very many repositories, you can do something like:
public IRepository<T> : IDisposable { }
public IJobRepository : IRepository<Job> { /* All the stuff you put here */ }
public JobRepository : IJobRepository
{
private IContext _context;
...
public void Dispose ()
{
if (_context != null)
{
_context.Dispose ();
}
}
public JobRepository (IContext context)
{
_context = context;
}
}
Then, how you use it depends on your specific task. I'm not a fan of this direct use of IRepository, but this answer is getting too long.

Design a class to be Unit testable

I am going though the Apress ASP.NET MVC 3 book and trying to ensure I create Unit Tests for everything possible but after spending a good part of a day trying to work out why edit's wouldn't save (see this SO question) I wanted to create a unit test for this.
I have worked out that I need to create a unit test for the following class:
public class EFProductRepository : IProductRepository {
private EFDbContext context = new EFDbContext();
public IQueryable<Product> Products {
get { return context.Products; }
}
public void SaveProduct(Product product) {
if (product.ProductID == 0) {
context.Products.Add(product);
}
context.SaveChanges();
}
public void DeleteProduct(Product product) {
context.Products.Remove(product);
context.SaveChanges();
}
}
public class EFDbContext : DbContext {
public DbSet<Product> Products { get; set; }
}
I am using Ninject.MVC3 and Moq and have created several unit tests before (while working though the previously mentioned book) so am slowly getting my head around it. I have already (hopefully correctly) created a constructor method to enable me to pass in _context:
public class EFProductRepository : IProductRepository {
private EFDbContext _context;
// constructor
public EFProductRepository(EFDbContext context) {
_context = context;
}
public IQueryable<Product> Products {
get { return _context.Products; }
}
public void SaveProduct(Product product) {
if (product.ProductID == 0) {
_context.Products.Add(product);
} else {
_context.Entry(product).State = EntityState.Modified;
}
_context.SaveChanges();
}
public void DeleteProduct(Product product) {
_context.Products.Remove(product);
_context.SaveChanges();
}
}
BUT this is where I start to have trouble... I believe I need to create an Interface for EFDbContext (see below) so I can replace it with a mock repo for the tests BUT it is built on the class DbContext:
public class EFDbContext : DbContext {
public DbSet<Product> Products { get; set; }
}
from System.Data.Entity and I can't for the life of me work out how to create an interface for it... If I create the following interface I get errors due to lack of the method .SaveChanges() which is from the DbContext class and I can't build the interface using "DbContext" like the `EFDbContext is as it's a class not an interface...
using System;
using System.Data.Entity;
using SportsStore.Domain.Entities;
namespace SportsStore.Domain.Concrete {
interface IEFDbContext {
DbSet<Product> Products { get; set; }
}
}
The original Source can be got from the "Source Code/Downloads" on this page encase I have missed something in the above code fragments (or just ask and I will add it).
I have hit the limit of what I understand and no mater what I search for or read I can't seem to work out how I get past this. Please help!
The problem here is that you have not abstracted enough. The point of abstractions/interfaces is to define a contract that exposes behavior in a technology-agnostic way.
In other words, it is a good first step that you created an interface for the EFDbContext, but that interface is still tied to the concrete implementation - DbSet (DbSet).
The quick fix for this is to expose this property as IDbSet instead of DbSet. Ideally you expose something even more abstract like IQueryable (though this doesn't give you the Add() methods, etc.). The more abstract, the easier it is to mock.
Then, you're left with fulfilling the rest of the "contract" that you rely on - namely the SaveChanges() method.
Your updated code would look like this:
public class EFProductRepository : IProductRepository {
private IEFDbContext context;
public EFProductRepository(IEFDbContext context) {
this.context = context;
}
...
}
public interface IEFDbContext {
IDbSet<Product> Products { get; set; }
void SaveChanges();
}
BUT... the main question you have to ask is: what are you trying to test (conversely, what are you trying to mock out/avoid testing)? In other words: are you trying to validate how your application works when something is saved, or are you testing the actual saving.
If you're just testing how your application works and don't care about actually saving to the database, I'd consider mocking at a higher level - the IProductRepository. Then you're not hitting the database at all.
If you want to make sure that your objects actually get persisted to the database, then you should be hitting the DbContext and don't want to mock that part after all.
Personally, I consider both of those scenarios to be different - and equally important - and I write separate tests for each of them: one to test that my application does what it's supposed to do, and another to test that the database interaction works.
I guess your current code looks something like this (I put in the interface):
public class EFProductRepository : IProductRepository {
private IEFDbContext _context;
// constructor
public EFProductRepository(IEFDbContext context) {
_context = context;
}
public IQueryable<Product> Products {
get { return _context.Products; }
}
public void SaveProduct(Product product) {
if (product.ProductID == 0) {
_context.Products.Add(product);
} else {
_context.Entry(product).State = EntityState.Modified;
}
**_context.SaveChanges();**
}
public void DeleteProduct(Product product) {
_context.Products.Remove(product);
**_context.SaveChanges();**
}
}
public class EFDbContext : DbContext, IEFDbContext {
public DbSet<Product> Products { get; set; }
}
public interface IEFDbContext {
DbSet<Product> Products { get; set; }
}
The problem is EFProductRepository now expects an object implementing the IEFDbContext interface, but this interface does not define the SaveChanges method used at the lines I put between the asteriskes so the compiler starts complaining.
Defining the SaveChanges method on the IEFDbContext interface solves your problem:
public interface IEFDbContext {
DbSet<Product> Products { get; set; }
void SaveChanges();
}

Proper way of using Unit of Work with unity injection

I am using unity, entity framework 4 with POCO classes, repository pattern for DAL and services for Business Logic control.
I also want to use Unit of Work so I can package together CRUD operations which I perform on different services and then commit them all together.
My question is what would be the proper way to inject the Unit Of Work mechanism into my application using Microsoft Unity?
I understand that I can put the IUnitOfWork together with the repository on the constructor of the proper service and then if Unity mapping is specified it would auto initiate the proper instances, but this way I do not pass the global unit of work but rather create a new instance on each level, which can't be a smart way to do it (actually the repository is initiated even before the service).
What am I missing? (Attached is constructor code as I wrote it now of service and its repository).
U also understand that I can use Unity's ParameterOverrides method to take some global instance of Unit of Work (lets say from my aspx.cs file) and pass it into the service and then into the repository. But it seems a bit lame. Is this my only option?
Thanks
public class GenericRepository<T> : IUnitOfWorkRepository, IGenericRepository<T> where T : BaseEntity, IAggregateRoot
{
private IUnitOfWork _uow;
/// <summary>
/// Returns the active object context
/// </summary>
private ObjectContext ObjectContext
{
get
{
return ObjectContextManager.GetObjectContext();
}
}
public GenericRepository(IUnitOfWork uow)
{
_uow = uow;
}
//blahhhh...
public void Add(T entity)
{
_uow.RegisterNew(entity, this);
}
public void Delete(T entity)
{
_uow.RegisterRemoved(entity, this);
}
//.....blah blah....
public void PersistCreationOf(IAggregateRoot entity)
{
this.ObjectContext.AddObject(GetEntitySetName(), entity);
}
public void PersistUpdateOf(IAggregateRoot entity)
{
// Do nothing as EF tracks changes
}
public void PersistDeletionOf(IAggregateRoot entity)
{
this.ObjectContext.DeleteObject(entity);
}
}
public class CategoryRepository : GenericRepository<XComSolutions.FB.Domain.Model.Entities.Category>, ICategoryRepository
{
public CategoryRepository(IUnitOfWork uow)
: base(uow)
{ }
}
public class CategoryService : ICategoryService
{
public int myID {get; set;}
private ICategoryRepository _categoryRepository;
private IUnitOfWork _uow;
public CategoryService(ICategoryRepository categoryRepository,
IUnitOfWork uow)
{
_categoryRepository = categoryRepository;
_uow = uow;
}
public List<Category> GetAll()
{
return _categoryRepository.GetAll();
}
}
Define an IUnitOfWorkFactory and inject that in your services:
public class Service
{
private readonly IUnitOfWorkFactory factory;
public Service(IUnitOfWorkFactory factory)
{
this.factory = factory;
}
public void DoOperation()
{
using (UnitOfWork context = this.factory.CreateNew())
{
this.DoSomeStuff(context);
this.DoMoreStuff(context);
context.SubmitChanges();
}
}
}
What I think you need to do is to define unit of work factory. You register this factory with your DI container and you resolve for this factory every time you need your unit of work. Then you get unit of work from the factory, work with it and let it go. You often will see that you need your unit of work within a scope of single method or single class. This article discuss Unit of Work pattern in connection with Entity Framework: http://msdn.microsoft.com/en-us/magazine/dd882510.aspx

Testable design

I have a java class which has a static member created using Facade (Singleton).
Class A implements InterfaceA {
private static DataStore db = DataStoreFacade.getInstance("BDB"); //singleton instance
public void save(final String key, final String val) {
db.save(key,val);
}
};
Here Class A is used as a member variable for webservice (stateless bean).
I can't test this code using EasyMock because there is no way to override the DataStore instance.
There are two options.
Have a constructor taking the instance of DataStore which will set to db member variable. The problem is I don't want webservice class to know which datastore instance has been created.
Provide an additional protected Set Method to override the db object. This is what I have used where I create a Easy Mock object of DataStore and override the member variable. Is it the correct design.
What are the other possibilities?
You're right that is bad for testability. Use dependency injection and don't go for static variable:
public class A implements InterfaceA {
private DataStore db;
public A(DataStore db) {
this.db = db;
}
...
}
to inject or build either use dependency-injection framework (e.g. spring) or build the object somewhere in bootstrap factory code yourself.
production code:
new A(DataStoreFacade.getInstance("...");
test-code:
public void test_xxx(){
DataStore db = EasyMock.createMock(DataStore.class);
//... do some expectations and replay(db)
InterfaceA a=new A(db);
//...
}
Well, the original code is already testable. Here is a unit test for it, using JMockit:
#Test
public void testSave(final DataStore mockDb)
{
final String key = "aKey";
final String value = "aValue";
new A().save(aKey, aValue);
new Verifications()
{{
mockDb.save(key, value);
}};
}
If needed, the DataStoreFacade class could be mocked too.
Why not make the db member protected, and in your test project inherit it and override that member:
project
{
Class A
{
protected static db = ...
public void Save(...) { ... }
}
}
test_project
{
Class B : A
{
protected override static db = ... (create test db)
}
Class testB
{
public A a;
public void Setup()
{
this.a = new B();
}
public void TearDown()
{
// delete a
}
public void TestSaveKey()
{
// test a
}
}
}
It's still hidden from consumers of the code/library, the test object isn't cluttering the production code, and the behaviour will be tested as if it were the production version.
Beware though, that having a static member for your db object could cause troubles for your tests if it's not cleaned up properly after each test.*
I know that you probably already know this, but I'm saying it for completeness.
Use the Supersede Instance pattern...
http://goodcoffeegoodcode.blogspot.com/2010/01/supercede-instance-pattern.html

Resources