I am having a custom context class in my ASP.NET 4.8 Framework website:
public sealed class MyCustomContext
{
private static readonly Lazy<MyCustomContext> staticContext =
new Lazy<MyCustomContext>(() => new MyCustomContext());
private MyCustomContext()
{
}
public static MyCustomContext Current => staticContext.Value;
public HttpContext Context => HttpContext.Current;
// Logic to return current user based on logged in user
public User LoggedInUser => ...
// Logic to return SiteWideSettings
public Collection<SiteWideSettings> SiteWideSettings => ...
}
The above class is a Singleton and the usage of the above class in my service class methods is like this:
public class MyService : IMyService
{
public MyService()
{
}
public void DoWork()
{
var current = MyCustomContext.Current;
var loggedInUser = current.LoggedInUser;
var siteWideSettings = current.SiteWideSettings;
var currentContext = current.Context;
// use the above properties further for this method
}
}
My goal is to remove MyCustomContext class dependency hardcoded in my DoWork method of MyService class so that it can look like this:
public class MyService : IMyService
{
private readonly IMyCustomContext _myCustomContext;
public MyService(IMyCustomContext myCustomContext)
{
_myCustomContext = myCustomContext;
}
public void DoWork()
{
var current = _myCustomContext.Current;
var loggedInUser = current.LoggedInUser;
var siteWideSettings = current.SiteWideSettings;
var currentContext = current.Context;
// use the above properties further for this method
}
}
Can you share how to convert my MyCustomContext class so that it can be injected via dependency injection into MyService?
I have one more question, do the properties like LoggedInUser, SiteWideSettings and Context of MyCustomContext class should be written as properties or they should be converted to methods for dependency injection?
For the dependency injection you need an interface which gets initialized, so your MyCustomContext class needs to implement a new interface called IMyCustomContext. The interface can look like following:
public interface IMyCustomContext
{
HttpContext Context { get; }
User LoggedInUser { get; }
Collection<SiteWideSettings> SiteWideSettings { get; }
}
public class MyCustomContext : IMyCustomContext
{
public HttpContext Context
{
get { return HttpContext.Current; }
}
public User LoggedInUser
{
get
{
// Logic to return current user based on logged in user
}
}
public Collection<SiteWideSettings> SiteWideSettings
{
get
{
// Logic to return SiteWideSettings
}
}
}
In the Startup.cs there is a method called ConfigureServices, there you can add the following for the dependency injection:
container.RegisterType<IMyCustomContext, MyCustomContext>(
TypeLifetime.Singleton);
It's worth pointing out that Singleton has dual meaning here:
The Singleton Design Pattern ensures an object is only instantiated once. Its implementation isn't ideal though, as it relies on ambient state.
The Singleton Lifetime is used by IOC frameworks, where it ensures the same reference of an object is used every time.
In short, the Singleton Lifetime effectively removes the need to implement the Design Pattern, because the IOC framework ensures the backing concept for you.
Meaning, if we register our dependency with the Singleton Lifetime.
container.RegisterType<ICustomContext, MyCustomContext>(TypeLifetime.Singleton);
We can remove the code for the Singleton Pattern, as the IOC container will take over the responsibility of guarding the single instance/reference.
public class MyCustomContext : ICustomContext
{
public HttpContext Context => HttpContext.Current;
// Logic to return current user based on logged in user
public User LoggedInUser => ...
// Logic to return SiteWideSettings
public Collection<SiteWideSettings> SiteWideSettings => ...
}
I've also added the ICustomContext interface with the member we're interested in.
public interface ICustomContext
{
HttpContext Context { get; }
User LoggedInUser { get; }
Collection<SiteWideSettings> SiteWideSettings { get; }
}
Can you share how to moq properties of that class?
That's right, we just moved the problem one level, didn't we? If you need to extract an interface, you usually need to do this in a recursive manner.
This also means HttpContext is not a good candidate for an interface member, which makes sense when you think about it. From a unit test's point of view, we're not interested in verifying ASP.NET's inner workings. Instead, we want to check our own code, and only that portion, with no dependencies on foreign libraries. To do so, you should only copy the HttpContext members you need on to your interface and remove the dependency on HttpContext (which is notoriously hard to abstract).
For example:
public interface ICustomContext
{
IPrincipal User { get; }
User LoggedInUser { get; }
Collection<SiteWideSettings> SiteWideSettings { get; }
}
This will require some refactoring / remodeling as the number of properties grows.
For simple DTO's you can even choose not to abstract / interface them, as long as your able to easily create fakes for unit testing. Also remember it only makes sense to introduce an interface if there are going to be multiple implementations.
One more thing about Dependency Inversion, and how IOC frameworks work, you usually let the dependencies bubble up. The recommended approach is through constructor injection, as illustrated in the following ICustomContext implementation for unit tests.
public class TestCustomContext : ICustomContext
{
public MyCustomContext(IPrincipal user, User loggedInUser, Collection<SiteWideSettings> siteWideSettings)
{
User = user;
LoggedInUser = loggedInUser;
SiteWideSettings = siteWideSettings;
}
IPrincipal User { get; }
User LoggedInUser { get; }
Collection<SiteWideSettings> SiteWideSettings { get; }
}
I have one more question, do the properties like LoggedInUser, SiteWideSettings and Context of MyCustomContext class should be written as properties or they should be converted to methods for dependency injection?
You can have both. If the state was injected through constructor injection, you might as well expose it as a property. If the implementing class implements behavior to create / transform the state, you might want to expose the behavior as a method. It all depends on the actual case, there is no golden bullet here. Just remember that in OO design, interfaces are used to model behaviors, with their scope kept as small as possible.
UPDATE
Those properties are not getting filled via constructor. All of these properties "IPrincipal User { get; } User LoggedInUser { get; } Collection SiteWideSettings { get; }" have the body in their getter, they get the data from cache first and if not found then it calls the service to get the data from db for those properties (all that is written in in the get of those properties). Should I keep them as properties only or make them methods?
Let me split up your question.
Should I keep them as properties only or make them methods?
From a technical point of view, it doesn't really matter. Properties, or automated properties (like the ones you're using), are just syntactic sugar over full blown methods. Meaning, they all get compiled into equivalent CIL instructions.
That leaves only the human factor. The readability and maintainability of your code. The agreed upon coding style and practices. That's not something I can answer for you. Personally, I prefer methods for handling these kind of code flows.
they get the data from cache first and if not found then it calls the service to get the data from db for those properties (all that is written in in the get of those properties).
Sounds like this class is more of a service provider than an actual model class in your domain. As there's also I/O involved, I'd definitely recommend switching to asynchronous methods on your interface. The explicit (Task based) signature says a lot to fellow developers reading your code.
The part where I talked about the dependencies bubbling up plays an important role here. The cache and repository are both dependencies of MyCustomContext. IOC and its inherent Dependency Inversion Principle rely on the explicit declaration of dependencies, as shown in the following sample. Note the implementation of GetLoggedInUser() is not what matters here, rather the way the dependencies are set through the constructor. All these dependencies need to be registered with your IOC container first, for it to be able to resolve ICustomContext.
public class MyCustomContext : ICustomContext
{
private readonly IUsersCache _usersCache;
private readonly IUsersRepo _usersRepo;
public MyCustomContext(IUsersCache usersCache, IUsersRepo usersRepo, IPrincipal principal)
{
_usersCache = usersCache;
_usersRepo = usersRepo;
Principal = principal;
}
public IPrincipal Principal { get; }
public async Task<LoggedInUser> GetLoggedInUser()
{
var userId = await GetUserId(Principal);
var user = _usersCache.GetById(userId);
if (user == null)
{
user = _usersRepo.GetById(userId);
_usersCache.Add(user);
}
return user;
}
...
}
Those properties are not getting filled via constructor. All of these properties "IPrincipal User { get; } User LoggedInUser { get; } Collection SiteWideSettings { get; }" have the body in their getter
I don't think that's true for IPrincipal as it, together with HttpContext, is instantiated by ASP.NET behind the scenes. All you need to do is tell the IOC container how to resolve the current IPrincipal and let it work its magic.
Likewise, all classes that depend on ICustomContext should have it injected by the IOC container.
public class MyService : IMyService
{
private readonly ICustomContext _customContext;
public MyService(ICustomContext customContext)
{
_customContext = customContext;
}
public async Task DoWork()
{
var currentPrincipal = _customContext.Principal;
var loggedInUser = await _customContext.GetLoggedInUser();
...
}
}
An important part here is again unit testing. If you design your classes like this, you can easily create fakes for testing. And even if there wasn't any testing involved, which I wouldn't recommend, the ability to decouple classes like this is a good indication of a well designed code base.
Related
I generate a singleton at runtime
public void ConfigureServices(IServiceCollection services)
{
var applications = Utils.generateApplications()
services.AddSingleton<ApplicationModel[]>(applications);
services.AddMvc();
}
How can I later update this dependency injected ApplicationModel[] with a completely new ApplicationModel[]. I have a feature in my application that the user can use to trigger a data refresh on the applications, but how can I update the underlying injected Singleton so all future injections will use the updated applications? I have a function Utils.generateApplications() that gets an up to date list of applications and returns a ApplicationModel[]. How do I overwrite the old injected Singleton with a new object to be injected into future calls if that makes sense?
I have some code :
public void UpdateData()
{
var applications = Utils.generateApplications()
//How do I set applications to replace the injected singleton for all future injections?
}
You should use an additional layer of indirection. I think the simplest way is to use an abstract factory. Define an interface something like this:
interface IApplicationModelFactory
{
public ApplicationModel[] GetModel();
}
Define a second interface with the method (or methods) needed to update the model:
interface IApplicationModelUpdate
{
void UpdateModel();
}
You can then change your ApplicationModel[] registration from single instance to scoped and delegate to the factory:
var modelFactory = new ApplicationModelFactory();
services.AddSingleton<IApplicationModelFactory>(modelFactory);
services.AddSingleton<IApplicationModelUpdate>(modelFactory);
services.AddScoped<ApplicationModel[]>(provider =>
provider.GetRequiredService<IApplicationModelFactory>().GetModel());
Inject IApplicationModelUpdate into the types that update the model and ApplicationModel[] into the types that use it. This has the advantage that all types resolved for the same request will get a consistent view of the model, even if it changes in the middle of processing that request.
You could also inject IApplicationModelFactory into the consumer code, but I think injecting the model directly is better. Using the factory can lead to different bits of code seeing different models during the same request. The mutability of the model is also an implementation detail that consumer code shouldn't have to worry about.
I wouldn't monkey with dependency injection that way. Instead, inject a factory, and write whatever logic you need to return the proper instance.
Simple factory:
interface IApplicationModelFactory
{
ApplicationModel[] Model { get; }
}
class ApplicationModelFactory : IApplicationModelFactory
{
public ApplicationModel[] Model { get; set; }
}
Registration:
services.AddSingleton<IApplicationModelFactory>
(
new ApplicationModelFactory[] { Model = util.generateApplications() }
)
class receiving the injection:
class Foo
{
protected readonly IApplicationModelFactory _factory;
public Foo(IApplicationModelFactory injected)
{
_factory = injected;
}
protected ApplicationModel[] => _factory.Model;
public void Bar()
{
DoSomethingWithModel(this.ApplicationModel);
}
}
My current class PropertyManager looks like this:
public class PropertyManager : IDisposable
{
private readonly IPropertyRepo _propertyRepo;
private readonly IUserTypeRepo _userTypeRepo;
public PropertyManager(IPropertyRepo propertyRepo, IUserTypeRepo userTypeRepo = null)
{
if (propertyRepo == null)
throw new ArgumentNullException("propertyRepo");
_propertyRepo = propertyRepo;
if (userTypeRepo != null)
_userTypeRepo = userTypeRepo;
}
}
My Property Manager will use the _userTypeRepo in some method to accomplish some task. I think I want to implment a rule that says "Each Manager(Service,Factory,etc) should be responsible for its own repository."
The idea:
The PropertyManager, because it needs to do something with the UserTypeRepo, I should be using the UserManager for such activities.
As such, this means that I will not provide a repo when creating an instance of the UserManager (i.e., var usrMgr = new UserManager(); // no repo). Instead, the UserManager will use the default constructor which will create a new instance of the IUserTypeRepo and provide a new instance of a UserManager and then it can do its work.
I think this accomplishes some design principle such as Separation of Concerns and the Single Responsibility, but then I may be getting away from my Dependency Injection design pattern as the new Managers would now have multiple constructors and look like this:
public class PropertyManager : IDisposable
{
private readonly IPropertyRepo _propertyRepo;
public PropertyManager(){
// use the default repo
_propertyRepo = new PropertyRepo();
}
// Used from Controller or Unit Testing
public PropertyManager(IPropertyRepo propertyRepo)
{
if (propertyRepo == null)
throw new ArgumentNullException("propertyRepo");
}
}
public class UserManager : IDisposable
{
private readonly IUserRepo _userRepo;
public UserManager(){
// use the default repo
_userRepo = new UserRepo();
}
// Used from Controller or Unit Testing
public UserManager(IUserRepo userRepo)
{
if (userRepo == null)
throw new ArgumentNullException("userRepo");
}
}
Would this be frowned upon? Or am I on the right track? In either case, why and thanks?
Update. After reading Yawar's post I decided to update my post and I think I have a relevant concern.
Let's think of a real world example of the above. I have a PropertyManager in real life named "Robert" one of the jobs he performs each morning at work is to Open() the Property (i.e., he unlocks the Property he is the Manager of). I also have a UserManger who manages people who visit the Property and her name is "Sarah" she has a function that she does called EnterProperty() (which is what she does in the morning when she physically walks into the building).
Rule: UserManager has a dependency on PropertyManager when using the EnterProperty()
This looks like this according to all accepted standards:
Property Manager
class PropertyManager : IPropertyManager
{
private readonly IPropertyRepo _propertyRepo;
public PropertyManager(IPropertyRepo propertyRepo)
{
if (propertyRepo == null)
throw new ArgumentNullException("propertyRepo");
this._propertyRepo = propertyRepo;
}
// this is when Robert opens the property in the morning
public void Open()
{
_propertyRepo.Open();
}
// this is when Robert closes the property in the evening
public void Close()
{
_propertyRepo.Close();
}
// this answers the question
public bool IsOpen()
{
return _propertyRepo.IsOpen();
}
}
User Manager
class UserManager : IUserManager
{
private readonly IPropertyRepo _propertyRepo;
private readonly IUserRepo _userRepo;
public UserManager(IUserRepo userRepo, IPropertyRepo propertyRepo = null)
{
if (userRepo == null)
throw new ArgumentNullException("userRepo");
this._userRepo = userRepo;
if (propertyRepo != null)
this._propertyRepo = propertyRepo;
}
// this allows Sarah to physically enter the building
public void EnterProperty()
{
if(_propertyRepo.IsOpen())
{
Console.WriteLine("I'm in the building.");
}else{
_propertyRepo.Open(); // here is my issue (explain below)
Console.WriteLine("Even though I had to execute the Open() operation, I'm in the building. Hmm...");
}
}
}
Web API Controller
{
public void OpenForBusiness(){
private const IPropertyRepo propertyRepo = new PropertyRepo();
private IPropertyManager propertyManager = new PropertyManager(propertyRepo);
private IUserManager userManager = new UserManager(new UserRepo(), propertyRepo);
// Robert, the `PropertyManager`, opens the `Property` in the morning
propertyManager.Open();
// Sarah, the `UserManager`, goes into `Property` after it is opened
userManager.EnterProperty();
}
}
Now, everything is cool and I can walk away and I now have a Repository Pattern which use Dependency Injection which supports TDD and not tightly coupled classes among other benefits.
However, is the truly realistic? (explain why I ask in second)
I think a more real-world (realistic) approach is one that does:
Web API Controller
public void Method1()
{
private IPropertyManager propMgr = new PropertyManager(new PropertyRepo());
private IUserManager userMgr = new UserManager(new UserRepo()); // no dependencies on any repository but my own
// 1. Robert, the `PropertyManager`, opens the `Property`
propMgr.Open();
// 2. Check to see if `Property` is open before entering
// choice a. try to open the door of the `Property`
// choice b. call or text Robert, the `PropertyManager`, and ask him if he opened the `Property` yet, so...
if(propMgr.IsOpen()){
// 3. Sarah, the `UserManager`, arrives at work and enters the `Property`
userMgr.EnterProperty();
}else{
// sol, that sucks, I can't enter the `Property` until the authorized person - Robert - the `PropertyManager` opens it
// right???
}
}
the EnterProperty() method on the UserManager now looks like this:
// this allows Sarah to physically enter the building
public void EnterProperty()
{
Console.WriteLine("I'm in the building.");
}
The promised explanation from above:
If we think in real-world terms we must agree that the later is preferred over the former. When thinking of a Repository lets say this is the definition of ones self (i.e., one's Person) (i.e., the UserRepo having all the data related to the User, is to the UserManager as the DNA, Heartbeat, Brain Wave Pattern, etc. is to a Human (the HumanRepo). As such, allowing the UserManager to know about the PropertyRepo and having access to its Open() method violates all Real-World security principles and Business Rules. In reality this says that through My Contructor() I can get an Interface Representation of a PropertyRepo that I can use any way I see fit. This is synonymous to the following logic of the HumanRepo:
I, Sarah - a UserManager - through a new instance of myself with the satisfaction of the PropertyRepo through my Constructor() create a Hologram Interface of Robert, the PropertyManager that I can use any way I see fit. Granted right now I only want to use the IsOpen() method of the PropertyRepo I actually use the Open() method to do it myself if Robert has not yet performed his duty. This is a security concern to me. In the real-world this says I don't have to wait for Robert to open the Property and use the Holocopy of him and implement his Open() method to get access.
That doesn't seem right.
I think with the last implementation I get SoC, SRP, DI, Repository Pattern, TDD, and Logical Security and as close to a real-world implementation as possible.
What do you all think?
I think I agree with your SoC and breaking the PropertyManager class into PropertyManager and UserManager classes. You are almost there.
I would just refactor as shown below:
public class PropertyManager : IDisposable, IPropertyManager
{
private readonly IPropertyRepo _propertyRepo;
// Used from Controller or Unit Testing
public PropertyManager(IPropertyRepo propertyRepo)
{
if (propertyRepo == null)
throw new ArgumentNullException("propertyRepo");
this._propertyRepo = propertyRepo;
}
}
public class UserManager : IDisposable, IUserManager
{
private readonly IUserRepo _userRepo;
// Used from Controller or Unit Testing
public UserManager(IUserRepo userRepo)
{
if (userRepo == null)
throw new ArgumentNullException("userRepo");
this._userRepo = userRepo;
}
}
Note: Just extract IPropertyManager & IUserManager so that the calling classes will depend upon the interfaces and provide the implementation.
Creating parameterless constructor is useless if you want to (you should) force the client to provide the concrete implementation of IPropertyRepo and IUserRepo interfaces.
public PropertyManager(){
// use the default repo
_propertyRepo = new PropertyRepo();
}
I dont think you would need
if (propertyRepo == null)
throw new ArgumentNullException("propertyRepo");
or
if (userRepo == null)
throw new ArgumentNullException("userRepo");
as IPropertyRepo and IUserRepo will be resolved via a IoC at the startup of your application (say its MVC then before calling the controller IoC will resolve them) so no need to check for null. I have never checked the dependencies for null in my code.
From what you have posted here thats pretty much it.
Unit of Work pattern is used for repository layer not in the manager layer. I would delete that from the title.
Hope this helps!
I think this accomplishes some OOP goal such as Separating Concerns
and the Single Responsibility Principle.
The result is opposite. Now, PropertyManager tightly couples to PropertyRepo; previously, they were loosely coupled.
First approach is better than the latter one. However, PropertyManager and UserManager should not create other objects on which they rely to do their work. The responsibility for creating and managing object should be offloaded to IoC container.
Interfaces describe what can be done, whereas classes describe how it is done. Only classes involve the implementation details—interfaces are completely unaware of how something is accomplished. Because only classes have constructors, it follows that constructors are an implementation detail. An
interesting corollary to this is that, aside from a few exceptions, you can consider an appearance of the new keyword to be a code smell. - Gary McLean Hall
Answer for Updated Question:
In your updated question, you combine Service/Manager and somewhat Domain into a single class - PropertyManager, UserManager. It becomes personal preference.
I personally like to keep them separate. In addition, I like to use Role based and Claim based authorization. Let me use my GitHub sample project as a reference. Please feel free to clone it.
User Domain
User class is also used by Entity Framework Code First Fluent API.
public partial class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
}
User Service
public class UserService : IUserService
{
private readonly IRepository<User> _repository;
public UserService(IRepository<User> repository)
{
_repository = repository;
}
public async Task<IPagedList<User>> GetUsersAsync(UserPagedDataRequest request)
{
...
}
}
Action Method
Notice that UI related Business Logic stays at UI layer.
public async Task<ActionResult> Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid)
{
bool result = _activeDirectoryService.ValidateCredentials(
model.Domain, model.UserName, model.Password);
if (result)
{
...
}
}
...
}
you can take quite a bit of a different approach.....( ignoring your repositories, but allowing for it to be injected )
In this system, the property is only readable, with an event system to handle the mutations, the event system also has rules system which controls what mutations are allowed. This means even if you have a property object you can't mutate it without going through its rules.
This code is more conceptual. The next logical step is to use a full actor model and something like (akka.net) and you may find your repository pattern just disappearing :)
public class Property
{
public string Name { get; private set; }
private IPropertyRules _rules;
private List<User> _occupants = new List<User>();
private IEventLog _eventLog;
public Property(IPropertyRules rules, IEventLog eventLog)
{
_rules = rules;
_eventLog = eventLog;
}
public ActionResult Do(IAction action, User user)
{
_eventLog.Add(action, user);
if (_rules.UserAllowedTo(action, user, this))
{
switch (action)
{
case Open o:
Open();
return new ActionResult(true, $"{user} opened {Name}");
case Enter e:
Enter(user);
return new ActionResult(true, $"{user} entered {Name}");
}
return new ActionResult(false, $"{Name} does not know how to {action} for {user}");
}
return new ActionResult(false, $"{user} is not allowed to {action} {Name}");
}
private void Enter(User user)
{
_occupants.Add(user);
}
private void Open()
{
IsOpen = true;
}
public bool IsOpen { get; set; }
}
public interface IEventLog
{
void Add(IAction action, User user);
}
public class Enter : IAction
{
}
public interface IPropertyRules
{
bool UserAllowedTo(IAction action, User user, Property property);
}
public class Open : IAction
{
}
public class ActionResult
{
public ActionResult(bool successful, string why)
{
Successful = successful;
WhatHappened = why;
}
public bool Successful { get; private set; }
public string WhatHappened { get; private set; }
}
public interface IAction
{
}
public class User
{
}
I have a scenario using WebApi, Generic Repository, EF6 and unit of work pattern
(in order to wrap all changes from several calls to the same context.)
Manager layer is used to perform calls to different repositories and also to other managers.
Currently Customer Manager does inject both repos and other Managers like:
public class CustomerManager {
public CustomerManager(IRepository<Customer> _customerRepository, IRepository<Order> orderRepository, IManager itemManager) {
_orderReporsitory = orderReporsitory;
_itemManager = itemManager;
_customerRepository = customerRepository;
}
public bool Save(Customer customer) {
_orderReporsitory.Find...
_itemManager.IsItemUnique(ItemId)
_customerRepository.Save(customer);
}
}
This code does not compile, for reference only.
Approaches like this
http://blog.longle.net/2013/05/11/genericizing-the-unit-of-work-pattern-repository-pattern-with-entity-framework-in-mvc/
Will wrap several repositories under a unit of work and flush the changes all together.
My issue involves also adding another Manager layer, to be wrapped also inside unit of work and allow both calls to repositories and other managers
(as I want to reuse some manager logic. Like in the example, I am re-using some ItemManager logic)
This code https://stackoverflow.com/a/15527444/310107
using (var uow = new UnitOfWork<CompanyContext>())
{
var catService = new Services.CategoryService(uow);
var custService = new Services.CustomerService(uow);
var cat = new Model.Category { Name = catName };
catService.Add(dep);
custService.Add(new Model.Customer { Name = custName, Category = cat });
uow.Save();
}
is using something similar of what I need but I would also like to be able to inject the services to unit test them (and not creating instances in the body of my manager/service method)
What would the best approach to do this ?
Thanks
Your code snippet with the unit of work has several problems, such as:
You create and dispose the unit of work explicitly within that method, forcing you to pass along that unit of work from method to method and class to class.
This causes you to violate the Dependency Inversion Principle, because you now depend on concrete types (CategoryService and CustomerService), which complicates your code and makes your code harder to test.
If you need to change the way the unit of work is created, managed or disposed, you will have to make sweeping changes throughout the application; A violation of the Open/Closed Principle.
I expressed these problems in more details in this answer.
Instead, I propose to have one DbContext, share it through a complete request, and control its lifetime in the application's infrastructure, instead of explicitly throughout the code base.
A very effective way of doing this is by placing your service layer behind a generic abstaction. Although the name of this abstraction is irrelevant, I usually call this abstraction 'command handler:
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
There are a few interesting things about this abstaction:
The abstraction describes one service operation or use case.
Any arguments the operation might have are wrapped in a single message (the command).
Each operation gets its own unique command class.
Your CustomerManager for instance, might look as follows:
[Permission(Permissions.ManageCustomerDetails)]
public class UpdateCustomerDetailsCommand {
public Guid CustomerId { get; set; }
[Required] public string FirstName { get; set; }
[Required] public string LastName { get; set; }
[ValidBirthDate] public DateTime DateOfBirth { get; set; }
}
public class UpdateCustomerDetailsCommandHandler
: ICommandHandler<UpdateCustomerDetailsCommand> {
public UpdateCustomerDetailsCommandHandler(
IRepository<Customer> _customerRepository,
IRepository<Order> orderRepository,
IManager itemManager) {
_orderReporsitory = orderReporsitory;
_itemManager = itemManager;
_customerRepository = customerRepository;
}
public void Handle(UpdateCustomerDetailsCommand command) {
var customer = _customerRepository.GetById(command.CustomerId);
customer.FirstName = command.FirstName;
customer.LastName = command.LastName;
customer.DateOfBirth = command.DateOfBirth;
}
}
This might look like just a bunch of extra code, but having this message and this generic abstraction allows us to easily apply cross-cutting concerns, such as handling the unit of work for instance:
public class CommitUnitOfWorkCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand> {
private readonly IUnitOfWork unitOfWork;
private readonly ICommandHandler<TCommand> decoratee;
public CommitUnitOfWorkCommandHandlerDecorator(
IUnitOfWork unitOfWork,
ICommandHandler<TCommand> decoratee) {
this.unitOfWork = unitOfWork;
this.decoratee = decoratee;
}
public void Handle(TCommand command) {
this.decoratee.Handle(command);
this.unitOfWork.SaveChanges();
}
}
The class above is a decorator: It both implements ICommandHandler<TCommand> and it wraps ICommandHandler<TCommand>. This allows you to wrap an instance of this decorator around each command handler implementation and allow the system to transparently save the changes made in the unit of work, without any piece of code having to do this explicitly.
It is also possible to create a new unit of work here, but the easiest thing to start with is to let the unit of work live for the duration of the (web) request.
This decorator will however just be the beginning of what you can do with decorators. For instance, it will be trivial to:
Apply security checks
Do user input validation
Run the operation in a transaction
Apply a deadlock retry mechanism.
Prevent reposts by doing deduplication.
Register each operation in an audit trail.
Store commands for queuing or background processing.
More information can be found in the articles, here, here and here.
I've been banging my head with this for days and still can't decide on which is the correct approach.
This question is targeting WPF specifically since as opposed to a web-application, many posts and articles online recommends a context per view-model approach and not a context per request.
I have a WPF MVVM application which is using an Entity-Framework DB first model.
here is an example of two models used in my app (created by EF Designer):
public partial class User
{
public User()
{
this.Role = new HashSet<Role>();
}
public string ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Role> Role { get; set; }
}
public class Role
{
public Role()
{
this.User = new HashSet<User>();
}
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<User> User { get; set; }
}
I've narrowed my options on how to handle this to the following:
1) Creating a DataAccess class which creates and disposes of the DbContext on each method call:
public class Dal
{
public User GetUserById(object userId)
{
using (var db = new DbEntities())
{
return db.User.Find(userId);
db.SaveChanges();
}
}
public void RemoveUser(User userToRemove)
{
using (var db = new DbEntities())
{
db.User.Remove(userToRemove);
db.SaveChanges();
}
}
}
which I can use in my ViewModel as follows:
public class UserManagerViewModel : ObservableObject
{
private readonly Dal dal = new Dal();
// models...
//commands...
}
2) Similar to approach 1 but without the Using statements:
public class Dal : IDisposable
{
private readonly DbEntities db = new DbEntities();
public User GetUserById(object userId)
{
return db.User.Find(userId);
db.SaveChanges();
}
public void RemoveUser(User userToRemove)
{
db.User.Remove(userToRemove);
db.SaveChanges();
}
public void Dispose()
{
db.SaveChanges();
}
}
The use is the same inside the ViewModel
3) Create a repository for each entity. Looks the same as the above options (also has the with or without the using dilemma), however every repository contains only methods related to its entity.
Afaik the use is the same as above inside my ViewModel.
4) Create a Unit-Of-Work class that will pass the appropriateRepository on demand:
public class UnitOfWork : IDisposable
{
private DbEntities db = new DbEntities();
private IUserRepository userRepository;
public IUserRepository UserRepository
{
get
{
return userRepository ?? new UsersRepository(db);
}
}
public void Save()
{
db.SaveChanges();
}
public void Dispose()
{
db.Dispose();
}
}
and use it inside my ViewModel as follows:
public class UserManagerViewModel : ObservableObject
{
private readonly UnitOfWork unit = new UnitOfWork();
// models...
//commands...
}
Which of the above approach (if any) is preferred in terms of in terms of data concurrency, better abstraction and layering and overall performance?
EDIT - Found the following paragraph in this article. :
When working with Windows Presentation Foundation (WPF) or Windows Forms, use a context instance per form. This lets you use change-tracking functionality that context provides.
However, it raises the question of whether I should create a DbContext object in my view-model or is it better to have a utility class such as my DAL class and reference it.
This is what dependency injection frameworks are designed to solve. Yes, it's yet another technology to add to your project, but once you start using DI you never look back.
The real problem here is that you're trying to make this decision in your view models when you really should be employing inversion of control and making the decision higher up. A WPF/MVVM application will want a context per-form so that changes are only submitted once a user is finished editing, and also to give the user the opportunity to cancel the changes. I know you're not using this in a web application but a well-designed architecture means you should be able to, in which case you'll want a context per request. You may want to write a console-app utility that populates the database with static data, in this case you may want a global/singleton context for performance and ease-of-use. Lastly, your unit tests also need to mock the context, probably on a per-test basis. All four of these cases should be set up in your injection framework and your view models should neither know or care about any of them.
Here's an example. I personally use Ninject, which is specifically designed for .NET. I also prefer NHibernate, although the choice of ORM is irrelevant here. I have session objects that have different scoping requirements, and this gets set up in a Ninject module that initializes my ORM classes:
var sessionBinding = Bind<ISession>().ToMethod(ctx =>
{
var session = ctx.Kernel.Get<INHibernateSessionFactoryBuilder>()
.GetSessionFactory()
.OpenSession();
return session;
});
if (this.SingleSession)
sessionBinding.InSingletonScope();
else if (this.WebSession)
sessionBinding.InRequestScope();
else
sessionBinding.InScope(ScreenScope);
This sets up the scoping for an ISession, which is the NHibernate equivalent of your context class. My repository classes, which manage the database objects in memory, contain a reference to the session they are associated with:
public class RepositoryManager : IRepositoryManager
{
[Inject]
public ISession Session { get; set; }
... etc...
{
The [Inject] attribute tells Ninject to populate this field automatically using the scoping rules I've set up. So far this is all happening in my domain classes, but it extends to my view model layer as well. In my scoping rules I pass in an object called "ScreenScope", and while I won't go into it here it basically means that any time I ask for a session object in my ScreenViewModel, or any view models that it has as members (including their own children) the same ISession object gets automatically created and passed in to all of them. By using DI scoping I don't even have to think about it, I just declare the members with the [Inject] attribute and it happens:
public class ScreenViewModel
{
[Inject] public CustomerService CustomerService { get; set; }
[Inject] public SalesService SalesService { get; set; }
[Inject] public BillService BillService { get; set; }
...etc...
}
These service classes all contains a RepositoryManager that has been injected, and since they're all in ScreenViewModel the ISession object will be the same, at least in my WPF build. if I switch to my MVC build they're the same for all view models created for a given request, and if I switch to a console build it uses the same ISession for everything in the entire program.
TL;DR: Use dependency injection and a scope your contexts to one-per-form.
In my earlier usage of MVVM within WPF I was utilising an open context per VM but I quickly ran into issues with thread safety of DBContexts once applications evolved to make better use of Async.
Whilst there is a greater development overhead, I now utilise dependency injection to provide a DBContextFactory (not the DBContext itself). I spin up a context in a using statement witihn the VM to fill observableCollections with plinq calls via EF. Another performance benefit of this method is running queries with AsNoTracking(). The annoying part is managing the reattachment of new or modified objects to the short lived context:
shortDBContext.Attach(myEntity).State = EntityState.Added; // or modified
await shortDBContext.SaveChangesAsync();
After introducing messaging in my application it seems I've found a bit of a smell.
In my multi tenant application, the file system is abstracted and scoped for each tenant. So if a service needs to create files, then we inject an instance of IFileSystem which will be scoped to the tenants directory/container.
This is achieved by configuring structuremap to construct the IFileSystem implementation by getting of a contextual object that has the current users site.
Now we need to use the filesystem when there is no context and no current user (on a background thread). Here's a simple example:
public class SiteContext
{
public string SiteId { get { return "Site123"; } }
}
public class FileSystemSettings
{
public string BaseDirectory { get; set; }
}
public interface IFileSystem { }
public class DefaultFileSystem : IFileSystem
{
public DefaultFileSystem(FileSystemSettings settings)
{
}
}
public interface ISomeService { }
public class SomeService : ISomeService
{
public SomeService(IFileSystem fileSystem)
{
}
}
public class TestMessageHandler : IMessageHandler<TestMessage>
{
public TestMessageHandler(ISomeService someService)
{
// oO we don't have access to site context here :(
}
}
I suppose I could change my FileSystem implementation to expose the FileSystemSettings as a property so it can be set afterwards.
However, even doing this would still require me to construct my ISomeService object manually, which is a pain as some of my services have a number of dependencies = lots of calls to ObjectFactory.GetInstance...
Ideas?
You could use nested containers and configure the nested container to have a dummy implementation of your context.
The code would approximately be:
using (var container = ObjectFactory.Container.GetNestedContainer())
{
container.Configure(config => {
config.For<ISiteContext>().Use<DummyContext>();
});
return container.GetInstance<TestMessageHandler>();
}
This should set a custom (dummy) implementation of ISiteContext without overwriting the global container (ObjectFactory.Container). Of course, I can't give you an appropriate implementation of DummyContext without more information. But this should get you started.