Im going through a tutorial which uses EF 6 and a UnitOfWork pattern. The idea is to introduce Autofac and im not entirely sure how i should convert this line of code so it fits in with the project to introduce Dependency Injection
private readonly ContactsContext _context;
public UnitOfWork(ContactsContext context)
{
_context = context;
Customers = new CustomerRepository(_context);
}
public ICustomerRepository Customers { get; }
I can't change
Customers = new CustomerRepository(_context);
to
Customers = new ICustomerRepository(_context);
Note the Interface as it throws an error.
I can post the ICustomerRepository if required but I don't know how I should be handling the dependency in this case?
I can post more code if required but I didn't know if this is enough and I'm missing something simple or not?
The standard way to do this would be to take a constructor dependency on ICustomerRepository instead of instantiating a CustomerRepository yourself within the constructor:
private readonly ContactsContext _context;
public UnitOfWork(ContactsContext context, ICustomerRepository customerRepository)
{
_context = context;
Customers = customerRepository;
}
public ICustomerRepository Customers { get; }
Of course, you will also need to register CustomerRepository with Autofac as the implementation of ICustomerRepository.
builder.RegisterType<CustomerRepository>().As<ICustomerRepository>();
This means that you will be relying on Autofac to create the repository instead of doing so yourself (Autofac will 'know' to inject the ContactsContext into the constructor of CustomerRepository). That's the pervasive aspect of dependency injection - it ends up requiring you to adopt it all the way down.
Related
I followed an online tutorial of the UnitOfWork pattern with Entity Framework as it has been awhile since I have used it. I am confused as to why in the tutorial the DataContext is a parameter of the public UnitOfWork constructor. This means if I use the UnitOfWork in another layer of the application, the other layer must be aware of the DataContext. This does not seem like a good separation of concerns. Am I missing something?
UnitOfWork:
public class UnitOfWork : IUnitOfWork
{
private readonly PurchasingDataContext _context;
public UnitOfWork(PurchasingDataContext context)
{
_context = context;
Items = new ItemRepository(_context);
Manufacturers = new LabelerRepository(_context);
Quotes = new QuoteRepository(_context);
Vendors = new VendorRepository(_context);
Contacts = new ContactRepository(_context);
}
public IItemRepository Items { get; private set; }
public ILabelerRepository Manufacturers { get; private set; }
public IQuoteRepository Quotes { get; private set; }
public IVendorRepository Vendors { get; private set; }
public IContactRepository Contacts { get; private set; }
public int Complete()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
Interface:
public interface IUnitOfWork : IDisposable
{
IContactRepository Contacts { get; }
IItemRepository Items { get; }
ILabelerRepository Manufacturers { get; }
IQuoteRepository Quotes { get; }
IVendorRepository Vendors { get; }
int Complete();
}
I am confused as to why in the tutorial the DataContext is a parameter of the public UnitOfWork constructor.
This is to make injecting the dependency into the UoW possible. By doing this, you can honor SRP easily.
With it, you can manage the scope of DataContext separately outside the UoW. This gives you much flexibility while using same UoW in different scenario (windows application vs web application for example). With this, you can expand database transactions the way you want.
This means if I use the UnitOfWork in another layer of the application, the other layer must be aware of the DataContext.
Yes; but not entirely true. Yes, the instance of DataContext should be managed (create, inject and dispose) by calling layer. That's it. That layer does not need to interact with with this instance in any way.
This does not seem like a good separation of concerns.
In continuation to earlier point, calling layer does not need to know how that instance work. All that part is abstracted in your UoW class. This is clean separation of concerns.
Am I missing something?
Hope you know that now.
I would start by asking why you are creating and exposing these repositories in your UnitOfWork. Having a single class that is responsible for a unit of work and the ownership of all of your repositories violates the Single Responsibility Principle. Your IUnitOfWork exposing every single repository that may or may not be needed by a caller violates the Interface Segregation Principle.
Instead of this approach, you should be using a dependency injection framework to manage the lifetimes of the context, repositories, and unit of work. The framework should ensure that one instance is created per request and shared across dependencies where needed.
A typical EntityFramework UnitOfWork would look similar to:
public interface IUnitOfWork
{
void SaveChanges();
}
with an implementation like:
public class UnitOfWork : IUnitOfWork
{
private readonly PurchasingDataContext _context;
public UnitOfWork(PurchasingDataContext context)
{
_context = context;
}
public void SaveChanges()
{
return _context.SaveChanges();
}
}
I develop an C# ASP.NET Core MVC app with a lot of razor pages.
Most of my razor pages use logging, sending e-mails and use multiple dbcontextes.
A lot of class looks like this:
class A : PageModel
{
private readonly ADbContext _context;
private readonly UserManager<ApplicationUser> _userManager;
private readonly IEmailSender _emailSender;
private readonly ILogger<MyModel> _logger;
public UpdateModel(ADbContext context,
UserManager<ApplicationUser> userManager,
IEmailSender emailSender,
ILogger<MyModel> logger)
{
_context = context;
_userManager = userManager;
_emailSender = emailSender;
_logger = logger;
}
}
I have 10+ pages like this.
When I create a page, I have to add these fields. So for a lot of times.
What would be the ideal approach to get rid of lot of field declarations? A base class that inherits every page model that I develop? But this base class would be a really general base class with logging, with Email and with contextes that really not similarly fit to each other.
Is it a good architectural choice to declare these fields every time I declare a class that uses them?
In general, yes, this is just what you do. Your dependencies are being injected, which means you need ivars to hold them and a constructor to accept them. It can feel and seem repetitive, but it's actually a good thing. It makes your class glanceable: you can quickly see what dependencies the class has at a glance.
You can create a base class if you like. However, you should be careful to only include things in your based class that are truly applicable to every derivation. The danger is in adding dependencies that aren't actually needed in all cases, and then now you have a bunch of pages loading dependencies they don't need and don't utilize.
You can also use abstractions to some extent here. For example, if each page depends on a context, but it might be different contexts in different scenarios, you can make the ivar typed as DbContext, instead of your concrete context type, and then you can set it to any valid derivation of DbContext. The same goes for your logger. You'd actually want to inject ILogger<MyPageModel>, but you can make the ivar on the base class just ILogger, which will then accept any logger.
Still, when you start to do this, you make it harder to suss out the dependencies of your classes, so it's a give and take. Personally, I'd only use a base class for shared logic, if any exists. If the only purpose of the base class is to define a particular set of dependencies, it's not worth having.
could it be a good occasion to use Filters instead ? Your filter dependencies could be injected via DI ?
https://www.learnrazorpages.com/razor-pages/filters
You can also simplify some cases of DI by injecting directly at function level where the service is required instead of inject at constructor level by adding '[FromService]' juste above the parameter :
[HttpGet]
public ActionResult OnGetDoSomething([FromServices] IEmailSender emailService)
{
// Do something
}
This way, you won't have to instanciate thoses services if the aren't required.
What about something like this?
class A : BasePage {
public UpdateModel(IServiceProvider provider) : base(provider) {
// here you can access the base properties
}
}
class BasePage : PageModel {
public ADbContext _context { get; set; }
public UserManager<ApplicationUser> _userManager; { get; set; }
public IEmailSender _emailSender; { get; set; }
public ILogger<MyModel> _logger; { get; set; }
public UpdateModel(IServiceProvider provider) : base(provider) {
Context = (ADbContext)provider.GetRequiredService(typeof(ADbContext));
UserManager = (UserManager)provider.GetRequiredService(typeof(UserManager));
EmailSender = (IEmailSender)provider.GetRequiredService(typeof(IEmailSender));
Logger = (ILogger)provider.GetRequiredService(typeof(ILogger));
}
}
There is a question I always ask myself when I'm using a Factory pattern inside my code (C#, but it applies to any language I suppose).
I have a "Service" that takes care of interacting with my database, do stuff with objects and interacts with my object model.
This Service uses a Factory sometimes to delegate the instanciation of an object.
But this factory obviously needs to interact by itself with the database to instanciate my object properly.
Is it a good/bad practice to pass the Database context to the Create method for example?
Like this :
var myNewObject = MyFactory.Create(myDatabaseContext);
the other way would be to let the Service always be the only one to talk with the database.
var myNewObject = MyFactory.Create();
var extraProperty = myDatabaseContext.Get(something);
myNewObject.extraProp = extraProperty;
Any advices?
The idea of passing the database context into the factory create method is called method injection. This is a form of dependency injection, so you are on the right track.
You can use dependency injection to manage your database context inside of your factory via the constructor. The factory could look something like this:
public class MyFactory
{
private readonly IMyDbContext dbContext;
public MyFactory(IMyDbContext dbContext)
{
this.dbContext = dbContext;
}
public object Create()
{
// Use the dbContext, etc
}
}
Constructor injection is usually favored because it leaves method signatures less cluttered. We will also most likely have one type of database context so there will be no need to take advantage of polymorphism based on some other runtime information.
You can choose to use a Dependency Injection Container like Ninject or, my favorite, SimpleInjector to manage the dependencies for you.
It is OK to have the DbContext only used by the factory. One thing you may want to watch out for is that a user of your factory may not realize that the factory is calling to the database. This could be a bad thing and have negative performance implications. Typically, construction information is passed into the factory method, not initialized into the factory method from the DB. You could even take it a step further and use the Repository Pattern to abstract away some more of the data access logic if you think it is necessary and you don't have that already.
To learn more about Dependency Injection, in case you are unfamiliar, you can start here.
My ideal structure may look like this:
public class MyFactory : IFactory
{
public object Create(object someProperty)
{
// build object
}
}
public class MyService
{
private readonly IMyDbContext dbContext;
private readonly IFactory factory;
public MyService(IMyDbContext dbContext, IFactory factory)
{
this.dbContext = dbContext;
this.factory = factory;
}
public void DoWork()
{
var property = dbContext.Get(something);
var newObj = factory.Create(property);
// Use stuff
}
}
In the project I am working on, we try to keep all database access inside the Service. If the Factory needs objects that must be loaded from the DB, the Service should load them and pass them to the Factory. If the object returned by the Factory shall be persisted, the Service should add it to the DbContext.
This corresponds to the second way you have shown. The advantage is that the Factory can be unit tested without any need to mock the DbContext.
If you want to keep the DB access inside the Factory anyways, I would inject the DbContext into the constructor of the Factory, instead of passing it to the Create() method.
The Service gets an instance of the Factory injected in turn (instead of accessing static methods of the Factory). Again, this will make mocking much easier.
public class Service {
private readonly IMyDbContext _myDatabaseContext;
private readonly IMyFactory _myfactory;
public Service (IMyDbContext myDbContext, IMyFactory myfactory) {
_myDatabaseContext = myDbContext;
_myfactory = myfactory
}
public void Create() {
var extraProperty = myDatabaseContext.Get(something);
var myNewObject = _myFactory.Create(extraProperty);
_myDatabaseContext.Add(myNewObject);
_myDatabaseContext.SaveChanges();
}
}
I'm using Repository and UoW pattern. My services look like this:
public class MyService : IService
{
private readonly IUnitOfWork<MyContext> unitOfWork;
private readonly IMyRepository myRepository;
public MyService(IUnitOfWork<MyContext> unitOfWork, IMyRepository myRepository)
{
this.unitOfWork = unitOfWork;
this.myRepository = myRepository;
}
//Methods...
}
Within services, I need to use other entities (for example to check for rights, etc).
Is it recommended to use the relevant repositories in the service or use the services directly?
Also, for each user we have rights (boolean) for each CRUD action. These rights are stored in the database.
Should checking of rights be done at the controller level or at the service level?
My golden rule is:
When you get business logic in your UI create a service, otherwise use
the repository directly.
So if you have this code in the UI:
var user = repos.Get(1);
user.FirstName = txtFirstName.Text;
repos.Save(user);
You are fine in my opinion. But if you instead have something like:
var user = userRepository.Get(1);
var accessChecker = authorizationRepository.GetForUser(id);
if (!accessChecker.MaySendEmail(user))
throw new SecurityException("You may not send emails");
var emailSender = new EmailSenderService();
emailSender.Send(user, txtDestination.Text, txtMessage.Text);
repos.Save(user);
It's likely that you should use a service instead.
Don't use your UoW to just wrap your database context. Since all your repositories are directly dependent of a given context (more or less, ofc), your repositories can be included in the UoW. Something along the lines of:
public interface IUnitOfWork<TContext> : IDisposable { }
public abstract class UnitOfWork<TContext> : IUnitOfWork<TContext> {
private readonly TContext _context;
protected TContext Context { get{ return _context; } }
protected UnitOfWork(TContext context){
_context = context;
}
}
public interface IMyDbUnitOfWork : IUnitOfWork<MyContext>{
public ICarRepository Cars { get; }
public IOwnerRepository Owners { get; }
}
public class MyDbUnitOfWork : UnitOfWork<MyContext>, IMyDbUnitOfWork{
public MyDbUnitOfWork():base(new MyContext()){}
private ICarRepository _cars;
public ICarRepository Cars {
get{
return _cars ?? (_cars = new CarRepository(Context));
}
}
private ICarRepository _owners;
public IOwnerRepository Owners {
get{
return _owners ?? (_owners = new OwnerRepository(Context));
}
}
}
public class MyService : IService
{
private readonly IMyDbUnitOfWork _unitOfWork;
public MyService(IMyDbUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
//Methods...
}
Obviously you can create this more or less generic, but I believe this should be enough to pass my point.
As a note, and since I normally use IoC frameworks, my services receive an IUnitOfWorkFactory because of the diferent lifestyles.
For the permissions question, it really depends how much control you want to have and how user friendly you want your application to be. Normally is a mix of both. Your application should know if your user has access to the screen but also if you must disable buttons accordingly. Since you also must prevent that, if by any reason, the user can invoke your service method, you can't allow it.
To solve this problem I don't filter by CRUD actions but by Service actions instead, intercepting every service invocation, which makes it easy to map my permissions to the user interface since normally is a 1 to 1 relation between button action and service action.
I think using repositories is just fine. I wouldn't invent a service layer for each of the repos.
Repository is used for abstracting the data access and service layer is to encapsulate business logic, however with recent trend , I find this overkill. Having service layer is fine if they act as controllers but don't try to map one to one to each entity or repo.
I typically use services from the UI and those services in turn use the repositories. I also find it useful to have some domain objects that encapsulate reusable logic in the services.
I do this so that rather than services calling each other and getting circular references, services use a common domain object instead. This avoids circular references and people copying and pasting the same code all over the place.This domain object may then use the repositories if necessary.
I have a simple repository that fetches some data using EF6. I'm also using a DI framework to inject the dependencies.
namespace Domain
{
public interface IMyRespository
{
List<MyObject> FetchObjects();
}
}
namespace Data
{
public class MyRepository : IMyRepository
{
private readonly MyDbContext _context;
public MyRepository(MyDbContext context)
{
_context = context;
}
public List<MyObjects> FetchObjects()
{
return _context.MyObjects.ToList();
}
}
}
A new requirement states that I need to log each FetchObjects() call and it's outputs. I thought this would be perfect example to apply the Decorator pattern.
namespace Domain
{
public class MyRepositoryDecorator : IMyRepository
{
private readonly IMyRepository _inner;
private readonly ILogRepository _logRepository;
public MyRepositoryDecorator(IMyRepository inner, ILogRepository logRepository)
{
_inner = inner;
_logRepository = logRepository;
}
public List<MyObjects> FetchObjects()
{
var objects = _inner.FetchObjects();
var logObject = new LogObject(objects);
_logRepository.Insert(logObject);
_logRepository.Save();
return objects;
}
}
}
Now I'm looking to employ the UnitOfWork pattern and I'm unsure how to implement in this case.
As I understand it some component needs to manage the UnitOfWork. So in this case a service class would make some calls and at the end call Save/Commit on the UnitOfWork class.
However if the repository interface indicates a readonly action there is no reason for the service class to wrap the call in a UnitOfWork and call Save/Commit at the end. It would look really weird too. However the decorator requires this to do it's job.
I'm probably missing some essential construct here. Any ideas on how to properly approach this scenario?
It would be a bad idea to mix UoW with Repository using Decorator (or similar) simply because it is not unusual for UoW to span across multiple repositories.
Also it is not up to the Repository to decide whether UoW should be committed or not. Repositories should know as less as possible about UoWs, ideally (and it is the case most of the time) nothing.
In your scenario the UnitOfWork class would pretty much only handles the transaction, so it can be implemented as a simple wrapper around TransactionScope, something like:
public sealed class UnitOfWork : IDisposable {
private readonly TransactionScope _transaction;
public UnitOfWork() { _transaction = new TransactionScope(); }
public void Commit { _transaction.Commit(); }
public void Dispose { _transaction.Dispose(); }
}
Now it is up to the service to instantiate/commit UoW, not up to Repository:
//assuming in a service
public void DoSomething() {
using(var uow = new UnitOfWork()) {
_repositoryA.UpdateSomething();
_repositoryB.DeleteSomething();
_uow.Commit();
}
}
And if your service only wants to read the data, then just do not use UnitOfWork in that operation (or use it without calling Commit so it will just be disposed).
In case if your repository needs to know about UoW, it will normally be passed as another parameter in its behavior method.
Note that it is not done because Repository wants to call Commit, but sometimes (rarely) it is needed for the repository to "enlist" to UoW. These cases are rather more complex.