Unit of Work with Repository having Generic methods - asp.net

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?

Related

Unit of work pattern not allowing me to create db context without options

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/

Entity framework, consuming context in webform app

Rather simple question regarding entity framework and how to consume the objectcontext.
In a asp.net webform application I am implementing most of data getters in a data class and trying to determine if its better (in a generic sense of better) to have a private context for the entire class or declare a context in each of the methods.
Example 1:
public class Data
{
private MyEntity context = new MyEntity();
public Customer GetCustomer()
{
return context.Customer.Single();
}
public Order GetOrder()
{
return context.Order.Single();
}
}
Or Example 2:
public class Data
{
public Customer GetCustomer()
{
using (MyEntity ctx = new MyEntity())
{
return context.Customer.Single();
}
}
public Order GetOrder()
{
using (MyEntity ctx = new MyEntity())
{
return context.Order.Single();
}
}
}
Personally im a big fan of using a shared context across your whole post back, however neither of these scenarios really achieve this. My personal preference is to use a dependency injection container such as ninject to manage the lifecycle of your EF context. This means that you can make your whole postback transactional.
in terms of implementation I would go for soemthing like the following:
public class Data
{
private MyContext _context;
public Data(MyContext context)
{
_context = context;
}
public Customer GetCustomer()
{
return _context.Customer.Single();
}
public Order GetOrder()
{
return _context.Order.Single();
}
}
with a binding similar to:
Bind<MyContext>().ToSelf().InRequestScope();

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.

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