I've been working with the entity framework for a little bit now, and I've come across several scenarios where two contexts would try to access the same entity etc, so I'm wondering if perhaps I'm not opening/closing my dbcontexts in the best way.
Currently I basically open a DbContext on each of my controllers the way the basic MVC app was set up originally, which means I have a private dbcontext field on the controller, and I override the controller's dispose method to call dispose on the context.
However I also sometimes make queries against the db in some of my other classes, which can get called from within the controller, which also has a context open.
Is there a way to access an open context without an explicit handler? It wouldn't really make sense for me to pass around a DbContext reference through a dozen different methods.
Using Dependency Injection
As others have said and will probably reiterate, the 'right way' is often considered to be dependency injection.
In my latest project, I've organized things so that I'm almost done with the project and DI has been so effortless that I'm doing it myself (rather than using an injector). One major factor in that has been adhering fairly strictly to this structure:
WebProject
| |
| DataServices
| | |
ViewModels EntityModels
Access to all data services during one unit of work occurs through a single DataServiceFactory instance, that requires an instance of MyDbContext. Another factor has been an entirely RESTful application design - it means I don't have to intersperse persistence functionality throughout my code.
Without Dependency Injection
That said, maybe DI isn't right for you on this project. Maybe:
you don't plan to write unit tests
you need more time to understand DI
your project structure already has EF deeply integrated
In ASP.NET MVC, the unit of work often entirely coincides with the request lifetime - i.e. HttpContext.Current. As a result, you can lazily instanciate a repository 'singleton' per-request, instead of using DI. Here is a classic singleton pattern with current context as the backing store, to hold your DbContext:
public class RepositoryProxy {
private static HttpContext Ctx { get { return HttpContext.Current; } }
private static Guid repoGuid = typeof(MyDbContext).GUID;
public static MyDbContext Context {
get {
MyDbContext repo = Ctx.Items[repoGuid];
if (repo == null) {
repo = new MyDbContext();
Ctx.Items[repoGuid] = result;
}
return repo;
}
}
public static void SaveIfContext() {
MyDbContext repo = Ctx.Items[repoGuid];
if (repo != null) repo.SaveChanges();
}
}
You can SaveChanges automatically too, if you are feeling especially lazy (you'll still need to call it manually to inspect side-effects, of course, like retrieving the id for a new item):
public abstract class ExtendedController : Controller {
protected MyDbContext Context {
get { return RepositoryProxy.Context; }
}
protected override void OnActionExecuted(ActionExecutedContext filterContext) {
RepositoryProxy.SaveIfContext();
base.OnActionExecuted(filterContext);
}
}
The "best" way to handle DbContext instances is to make it a parameter on each method that needs it (or, if an entire class needs it, a parameter to the constructor).
This is a basic part of IoC (Inversion of Control) which allows the caller to specify dependencies for a method thus allowing the caller to "control" the behavior of the called method.
You can then add a Dependency Injection framework as well. They can be configured to use a singleton instance of your DbContext and inject that instance into any methods that need it.
Instead of passing instance of DbContext I would suggest you pass instance of some kind of factory class, that will create an instance of DbContext for you.
For most scenarios you can just create interface, that your DbContext will implement, something like this:
public interface IDbContext
{
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
DbSet Set(Type entityType);
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
int SaveChanges();
}
and then a factory to return your instance:
public interface IContextFactory
{
IDbContext Retrieve();
}
The factory can be easily mocked to return whatever implementation you want - which is a good approach especially if you intend to test the application. Your DbContext will just derive from IDbContext interface and implement necessary methods and properties. This approach assumes, that to tell EF about your database tables you use OnModelCreating(DbModelBuilder modelBuilder) method and with modelBuilder.Configurations.Add(new EntityTypeConfiguratinOfSomeType()); instead of having properties of type DbSet<T> all around your context.
To completely abstract from Entity framework, you can create yet another layer of abstraction, for example with UnitOfWork or Repository pattern approaches, but I guess the former covers your concerns for now.
Related
This is in a .NET Core project. In the Startup I register a singleton for my translation service that gets initialized with configuration settings from appsettings.json. Once it's set the whole app will use that service. This works great in my controllers and repositories, I just define the constructor to take that interface and it injects as expected:
services.AddSingleton<Foo.Bar.ITranslationService>(
new Foo.Bar.SomeTranslator(config.TranslationSettings));
But the issue I ran into is one where a POCO needed to use that translation service. And my POCOs all get generated as generics by the repository, so for example a repository method might look like this:
public TEntity GetById(object id){
return connection.Get<TEntity>(id);
}
So the repository has the injected TranslationService passed into it, but is there a way to cleanly pass that along to the POCO that needs it using DI? Or do I need to hack it somehow? I'm trying to figure out the cleanest way to do this, thanks!
How about property injection?
public TEntity GetById(object id){
var entity = connection.Get<TEntity>(id);
if (entity is ITranslatable t)
{
t.Translator = _translationService;
}
return entity;
}
You basically need to add the translation interface to the constructor of that object.
public class MYPOCO
{
private Foo.Bar.ITranslationService translator
public MYPOCO(Foo.Bar.ITranslationService translator)
{
this.translator = translator;
}
}
This then allow you to use the translator service in the class. But your going to run into a number of issues there.
Unless the framework explicitly creates your POCO then it will not
get injected. For example it would need to be a Controller of some
sort that would be created by the framework as soon as a route is
called.
You may need your own factories to create instances of the POCO.
To keep the POCO as clean as possible, you probably want a Factory, which would create an instance of your POCO and set the translations appropriately. The Factory would take an instance of the translator service.
I use Ninject for DI, it creates DbContext per request (single for all services) and i usually call few service methods per request (so i can't dispose DbContext after first service method has been called).
The question is, should i make WallService or WallManager (and other services and managers) IDisposable and what Dispose logic create?
My Business Logic Layer
namespace MySite.BLL.Services
{
public class WallService
{
WallManager wallManager;
public WallService(MybContext db)
{
wallManager = new WallManager(db);
}
}
}
My Data Access Layer
namespace MySite.DAL.Repositories
{
public class WallManager
{
MyDbContext db;
public WallManager(MyDbContext db)
{
this.db = db;
}
}
}
NinjectWebCommon.cs
kernel.Bind<MyDbContext>().ToSelf().InRequestScope().WithConstructorArgument<string>("MyMsSqlString");
kernel.Bind<WallService>().ToSelf().InRequestScope();
MyBaseController.cs
public class MyBaseController : Controller
{
[Inject]
public WallService WallService { get; set; }
// Other Services ..
}
(This is more an extended comment than an answer)
I'm pretty certain you don't need to do this - and not only that you don't need to but you really shouldn't in this case.
The thing is, you are not creating the DbContext instance yourself - you're delegating that responsibility to the IOC library;in that respect the reference is only "passing through" so none of your classes own it and should not do anything that could trash it.
Also, DbContext is a managed object so you don't need to Dispose it anyway.
There is a very good answer on this site about this notion already, although it doesn't directly address your question hence I didn't mark as duplicate
One thing I've noticed about your code though.
You're injecting the DbContext, and then using it to create a WallManager instance. That's kind of defeating the purpose of Dependency Injection. Why not directly inject the WallManager into WallService?
i.e.
public class WallService
{
readonly WallManager _wallManager;
public WallService(WallManager manager)
{
if (manager==null){
throw new ArgumentNullException("manager");
}
_wallManager = manager;
}
}
Ninject (or any other IOC Library) will have no problem figuring out that it needs to create and inject a DbContext into the manager dependency, once you have registered the WallManager type with it; the idea here is that you register all possible dependency types, and then the library builds the object graph for you.
This way you don't have to take a dependency on DbContext directly in your WallService...I am guessing you only take it in order to create the WallManager anyway - if you are also using DbContext in the WallService I would suggest you take another look at the design since you should limit your data access to one layer.
I've inherited a WPF MVVM application which has virtually no unit tests. When I tried to write my own, I quickly realised why: the code hasn't been written in a manner that makes it easy to test, with a lot of concrete implementations.
A particular bugbear is the repository. There's an EF context underneath which I can't/don't want to test but I'm struggling to even get the thing to accept Mocks of the EF objects instead.
I'll hold my hand up and say: I'm not a very good architect. Can you help me untangle this a bit, and prod me toward where interfaces and such need to be added?
Here's a sample ViewModel from the application:
public class MyViewModel : BaseViewModel
{
public MyViewModel(MyEFObject mEfObj)
{
//do stuff
}
// properties, methods etc etc
}
They all inherit from BaseViewModel:
public abstract class BaseViewModel : INotifyPropertyChanged
{
private static MyRepository _rep;
protected static MyRepository rep
{
get
{
if (_rep == null)
_rep = new MyRepository();
return _rep;
}
}
// properties, methods etc etc
}
And so to the repository class:
public class MyRepository
{
private MyEntitiesT db = new MyEntitiesT();
//methods and properties that interact with the DB
}
And finally, at the bottom of the heap, that slightly peculiar entity wrapper:
public class MyEntitiesT : MyEntities
{
public MyEntitiesT()
{
var objectContext = (this as IObjectContextAdapter).ObjectContext;
objectContext.CommandTimeout = 0;
}
}
So, I guess I really need an IMyRepositoryInterface over MyRepository, which would allow me to Mock that. But if I'm instantiating a MyViewModel object, how do I get in my mocked repository, since it's specified in BaseViewModel? Do I need to start fiddling with dependency injection?
Poor testability aside, this is a pretty functional application that I don't want to mess with excessively for fear of breaking it. So if there's a way I can get these things decoupled without making major structural changes, or at least by making them piecemeal (i.e. one ViewModel at a atime) it'd be useful.
You are right. You need IRepository and an implementation containing all the EF code like EfRepository.
I also saw that you are passing and EF Object to a ViewModel...
MyEFObject mEfObj
usually you just want to retrieve POCO's from your Repositories and pass in the Repository to the view model.
So start piece by piece. Take your existing repository and define an interface for it and implement it in the repository. And start to exchange the concrete class definition in the constructor with the interface... and then work from there how deep you need and want to go...
And start adding tests on your way... they will build up soon...
Before you use Dependency injection framework start with something like this...
private readonly IRepository _repository;
public MyViewModel() : this(new EfRepository())
{
}
public MyViewModel(IRepository repository)
{
_repository = repository;
}
This should only be an intermediate step but helps you to refactor to implement a contract based on interfaces. After that look for DI and ViewModelLocator pattern
To go with constructor injection and Interfaces is a good step because they are easy mockable and you can also use mocking frameworks to provide expected behavior from within your unit test.
HTH
Okay, I'm going to try and go short and straight to the point. I am trying to develop a loosely-coupled, multi-tier service application that is testable and supports dependency injection. Here's what I have:
At the service layer, I have a StartSession method that accepts some key data required to, well, start the session. My service class is a facade and delegates to an instance of the ISessionManager interface that is injected into the service class constructor.
I am using the Repository pattern in the data access layer. So I have an ISessionRepository that my domain objects will work with and that I implement using the data access technology du jour. ISessionRepository has methods for GetById, Add and Update.
Since my service class is just a facade, I think it is safe to say that my ISessionManager implementation is the actual service class in my architecture. This class coordinates the operations with my Session domain/business object. And here's where the shell game and problem comes in.
In my SessionManager class (the concrete ISessionManager), here's how I have StartSession implemented:
public ISession StartSession(object sessionStartInfo)
{
var session = Session.GetSession(sessionStartInfo);
if (session == null)
session = Session.NewSession(sessionStartInfo);
return session;
}
I have three problems with this code:
First, obviously I could move this logic into a StartSession method in my Session class but I think that would defeat the purpose of the SessionManager class which then simply becomes a second facade (or is it still considered a coordinator?). Alas, the shell game.
Second, SessionManager has a tightly-coupled dependance upon the Session class. I considered creating an ISessionFactory/SessionFactory that could be injected into SessionManager but then I'd have the same tight-coupling inside the factory. But, maybe that's okay?
Finally, it seems to me that true DI and factory methods don't mix. After all, we want to avoid "new"ing an instance of an object and let the container return the instance to us. And true DI says that we should not reference the container directly. So, how then do I get the concrete ISessionRepository class injected into my Session domain object? Do I have it injected into the factory class then manually pass it into Session when constructing a new instance (using "new")?
Keep in mind that this is also only one operation and I also need to perform other tasks such as saving a session, listing sessions based on various criteria plus work with other domain objects in my solution. Plus, the Session object also encapsulates business logic for authorization, validation, etc. so (I think) it needs to be there.
The key to what I am looking to accomplish is not only functional but testable. I am using DI to break dependencies so we can easily implement unit tests using mocks as well as give us the ability to make changes to the concrete implementations without requiring changes in multiple areas.
Can you help me wrap my head around the best practices for such a design and how I can best achieve my goals for a solid SOA, DDD and TDD solution?
UPDATE
I was asked to provide some additional code, so as succinctly as possible:
[ServiceContract()]
public class SessionService : ISessionService
{
public SessionService(ISessionManager manager) { Manager = manager; }
public ISessionManager Manager { get; private set; }
[OperationContract()]
public SessionContract StartSession(SessionCriteriaContract criteria)
{
var session = Manager.StartSession(Mapper.Map<SessionCriteria>(criteria));
return Mapper.Map<SessionContract>(session);
}
}
public class SessionManager : ISessionManager
{
public SessionManager() { }
public ISession StartSession(SessionCriteria criteria)
{
var session = Session.GetSession(criteria);
if (session == null)
session = Session.NewSession(criteria);
return session;
}
}
public class Session : ISession
{
public Session(ISessionRepository repository, IValidator<ISession> validator)
{
Repository = repository;
Validator = validator;
}
// ISession Properties
public static ISession GetSession(SessionCriteria criteria)
{
return Repository.FindOne(criteria);
}
public static ISession NewSession(SessionCriteria criteria)
{
var session = ????;
// Set properties based on criteria object
return session;
}
public Boolean Save()
{
if (!Validator.IsValid(this))
return false;
return Repository.Save(this);
}
}
And, obviously, there is an ISessionRepository interface and concrete XyzSessionRepository class that I don't think needs to be shown.
2nd UPDATE
I added the IValidator dependency to the Session domain object to illustrate that there are other components in use.
The posted code clarifies a lot. It looks to me like the session class holds state (with behavior), and the service and manager classes strictly perform actions/behavior.
You might look at removing the Repository dependency from the Session and adding it to the SessionManager. So instead of the Session calling Repository.Save(this), your Manager class would have a Save(ISession session) method that would then call Repository.Save(session). This would mean that the session itself would not need to be managed by the container, and it would be perfectly reasonable to create it via "new Session()" (or using a factory that does the same). I think the fact that the Get- and New- methods on the Session are static is a clue/smell that they may not belong on that class (does this code compile? Seems like you are using an instance property within a static method).
Finally, it seems to me that true DI
and factory methods don't mix. After
all, we want to avoid "new"ing an
instance of an object and let the
container return the instance to us.
And true DI says that we should not
reference the container directly. So,
how then do I get the concrete
ISessionRepository class injected into
my Session domain object? Do I have it
injected into the factory class then
manually pass it into Session when
constructing a new instance (using
"new")?
This question gets asked a LOT when it comes to managing classes that mix state and service via an IOC container. As soon as you use an abstract factory that uses "new", you lose the benefits of a DI framework from that class downward in the object graph. You can get away from this by completely separating state and service, and having only your classes that provide service/behavior managed by the container. This leads to passing all data through method calls (aka functional programming). Some containers (Windsor for one) also provide a solution to this very problem (in Windsor it's called the Factory Facility).
Edit: wanted to add that functional programming also leads to what Fowler would call "anemic domain models". This is generally considered a bad thing in DDD, so you might have to weigh that against the advice I posted above.
Just some comments...
After all, we want to avoid "new"ing an instance of an object and let the container return the instance to us.
this ain't true for 100%. You want to avoid "new"ing only across so called seams which basically are lines between layers. if You try to abstract persistence with repositories - that's a seam, if You try to decouple domain model from UI (classic one - system.web reference), there's a seam. if You are in same layer, then decoupling one implementation from another sometimes makes little sense and just adds additional complexity (useless abstraction, ioc container configuration etc.). another (obvious) reason You want to abstract something is when You already right now need polymorphism.
And true DI says that we should not reference the container directly.
this is true. but another concept You might be missing is so called composition root (it's good for things to have a name :). this concept resolves confusion with "when to use service locator". idea is simple - You should compose Your dependency graph as fast as possible. there should be 1 place only where You actually reference ioc container.
E.g. in asp.net mvc application, common point for composition is ControllerFactory.
Do I have it injected into the factory class then manually pass it into Session when constructing a new instance
As I see so far, factories are generally good for 2 things:
1.To create complex objects (Builder pattern helps significantly)
2.Resolving violations of open closed and single responsibility principles
public void PurchaseProduct(Product product){
if(product.HasSomething) order.Apply(new FirstDiscountPolicy());
if(product.HasSomethingElse) order.Apply(new SecondDiscountPolicy());
}
becomes as:
public void PurchaseProduct(Product product){
order.Apply(DiscountPolicyFactory.Create(product));
}
In that way Your class that holds PurchaseProduct won't be needed to be modified if new discount policy appears in sight and PurchaseProduct would become responsible for purchasing product only instead of knowing what discount to apply.
P.s. if You are interested in DI, You should read "Dependency injection in .NET" by Mark Seemann.
I thought I'd post the approach I ended up following while giving due credit above.
After reading some additional articles on DDD, I finally came across the observation that our domain objects should not be responsible for their creation or persistence as well as the notion that it is okay to "new" an instance of a domain object from within the Domain Layer (as Arnis eluded).
So, I retained my SessionManager class but renamed it SessionService so it would be clearer that it is a Domain Service (not to be confused with the SessionService in the facade layer). It is now implemented like:
public class SessionService : ISessionService
{
public SessionService(ISessionFactory factory, ISessionRepository repository)
{
Factory = factory;
Repository = repository;
}
public ISessionFactory Factory { get; private set; }
public ISessionRepository Repository { get; private set; }
public ISession StartSession(SessionCriteria criteria)
{
var session = Repository.GetSession(criteria);
if (session == null)
session = Factory.CreateSession(criteria);
else if (!session.CanResume)
thrown new InvalidOperationException("Cannot resume the session.");
return session;
}
}
The Session class is now more of a true domain object only concerned with the state and logic required when working with the Session, such as the CanResume property shown above and validation logic.
The SessionFactory class is responsible for creating new instances and allows me to still inject the ISessionValidator instance provided by the container without directly referencing the container itself:
public class SessionFactory : ISessionFactory
{
public SessionFactory(ISessionValidator validator)
{
Validator = validator;
}
public ISessionValidator Validator { get; private set; }
public Session CreateSession(SessionCriteria criteria)
{
var session = new Session(Validator);
// Map properties
return session;
}
}
Unless someone can point out a flaw in my approach, I'm pretty comfortable that this is consistent with DDD and gives me full support for unit testing, etc. - everything I was after.
I'm a bit confused about when using the "IRepository pattern", when actually to load the data.
Currently I have something like this:
public class MainViewModel : ViewModelBase
{
// EF4 generated ObjectContext
private ScorBotEntities context = new ScorBotEntities();
// Custom IUserRepository class
private IUserRepository userRepository;
public MainViewModel()
{
this.userRepository = new UserRepository(context.Users);
}
public ObservableCollection<User> Users
{
get
{
return new ObservableCollection<User>(userRepository.GetAll());
}
}
}
ScorBotEntities are autogenerated using EF4 (I had a look at POCOs, to much work for this sized project).
You can find the definition of the UserRepository here: http://code.google.com/p/i4prj4-g2/source/browse/ScorBotRobotics/ScorBotRobotics/Repositories/UserRepository.cs
But basically, what I'm wondering about is, why do it even make sense to use a repository here, instead of just writing it like this:
public class MainViewModel : ViewModelBase
{
private ScorBotEntities context = new ScorBotEntities();
public MainViewModel()
{
}
public ObservableCollection<User> Users
{
get
{
return new ObservableCollection<User>(context.Users);
}
}
}
It makes sense to abstract functionality away such as with the UsernameAndPassword method. But in that case, perhaps using some Query Objects would be more ideal?
I am a bit baffled that your context has made its way down to your ViewModel. I believe your GUI layer should never see the context. Context must be opened/kept/closed by the IRepository. Let the data layer (IRepository) return an array/list of Users.
There are a couple of different points here. First, your view models should have no knowledge of the repository - keep your view models as simple as possible.
Second, the IRepository is your public API - so you should have dependencies to this (depend on abstractions rather than concrete implementation between layers).
There are a couple of different (perfectly acceptable ways) to implement the IRepository. One is to have the repository encapsulate the context directly. Another is to use the "unit of work" pattern and have your unitOfWork encapsulate the context and pass the unitOfWork object to each repository. Either way, since you're using EF4, testability is much easier than it used to be. For example, EF4 introduced IObjectSet so that it is easy to provide test doubles and mocks to test your repository.
I highly recommend checking out this whitepaper on Testability and Entity Framework 4.
Separation of concerns
What if you want to change the storage of 'Users', from say SQL to a flat file?
Then context would not be needed, and you'd have to change every use of it, instead of just your IRepository implementation.
Also, ideally you would have your IRepository injected. So you're MainViewModel doesn't care how it gets it's Users.