Thank you for helping me understand some of this stuff:
Say I have 2 controllers in an MVC application -
1 controls viewModels related to salespeople
1 controls viewModels related to sales
Each have a their own repository, which access data using Entity framework (code first)
both repositories are set up to handle dependency injection, but also have 0 argument constructors with defaults to use the appropriate EF dataAccess.
the salespeople controller uses a _salesPeopleRepository.getAllSalesPeople() function which returns a List of salespeople to populate an index view.
the sales controller needs to access the same list to populate a dropdownlist.
there are several ways to get the information to the sales controller, and I was wondering which options would be considered best practice:
a) In the controller
db = new DataContext();
_saleRepos = new SalesRepository(db);
_salesPeople = new SalesPeopleRepository(db);
.....
modelA.SalePeopleSelectList = SelectList(_salesPeople.getAllSalesPeople(),"id","name")
b) in the SalesRepository - either using EF itself:
public IEnumerable<salesPerson> getAllSalesPeople()
{
return _db.SalesPeople.ToList();
}
c) or instantiating and injecting the same data access object before calling the function
public IEnumerable<salesPerson> getAllSalesPeople()
{
return (new SalesPersonRepository(_db)).getAllSalesPeople();
}
Edit
If the answer is a), how should custom buisiness logic be called from 1 repository - say for instance sales has a storeId and the repository checks that the storeId entered for the sale matches the storeId for the salesPerson. Should the salesPerson object used for buisness logic purposes (within the salesRepository) be accessed via the salesPerson repository, or directly from the dataContext object?
Thank you for your thoughts and experience
It doesn't make sense to have your SalesRepository retrieving data from the SalesPerson table. That data access logic ought to be centralized in the SalesPeopleRepository. Duplicating the method across repositories will just muddy the water, in my opinion.
So why not have both the SalesRepository and SalesPeopleRepository used in your Sales Controller? I would just instantiate an instance of the SalesPeopleRepository and use the method already defined in there.
Also, if your Controllers are using dependency injection, you could just have the repositories passed in to the constructor:
public SalesController (ISalesRepository salesRepository, ISalesPeopleRepository salesPeopleRepository)
{
this._salesRepository = salesRepository;
this._salesPeopleRepository = salesPeopleRepository;
}
Best Practice always depends on the context, but a combination of the Repository and Unit Of Work patterns are regularly used on top of EF.
Usage:
using (var uow as new DataContext()) {
var salesPeople = new SalesPeopleRepository(uow);
// ...
uow.Commit(); // If changes must be committed back to the database
}
Implementation:
public interface IUnitOfWork {
public void Commit();
}
public class DataContext : IUnitOfWork {
public void Commit() {
this.SaveChanges();
}
}
public class SalesPeopleRepository {
private DataContext _db
public SalesPeopleRepository(IUnitOfWork uow) {
_db = uow as DataContext;
}
public IEnumerable<SalesPerson> GetAllSalesPeople() {
return _db.SalesPeople.ToList();
}
}
First, the C# naming convention should be followed: getAllSalesPeople() should be GetAllSalesPeople. Second, IoC Container and dependency injection would be the best practice in this case.
The item a should be avoied because DataContext and Repositories are created directly in controller, it is violating dependency injection and make your code tight coupling with Repositories and DataContext and no way to mock for unit testing. Instead, repositories should be injected into controllers and DataContext should be injected into Repositories.
public Repository(DataContext dataContext)
{
_dataContext = dataContext;
}
public SalesController(ISalesRepository salesRepository,
ISalesPeopleRepository salesPeopleRepository)
{
_salesRepository = salesRepository;
_salesPeopleRepository = salesPeopleRepository;
}
The lifetime management for DataContext should be kept in per request in IoC Container instead of creating directly in controller, most of IoC Container supports this. Don't know which IoC container you use, but my faves is: Autofac and Windsor.
For the item c, you are making the business logic leak to Repository layer, instead, business logic should be in controller or in separate layer. Repository just deal with CRUD operation with your database.
Related
In my asp mvc Framework project, using EF, I have some objects (from classes) whose fields store data coming from my database.
My question is :
How to populate these fields, or manage methods of these objects using a dbcontext variable ?
Sol 1: Is it better to use each time I need a connection with db in my classes with the instruction (using (resource), see below ) ?
Sol 2: Is it betterI to code a singleton class to use one instance of the context ?
Sol 3: Or should I use another way for the links beetween my classes and the database ?
What is the best method considering performances and code quality.
Thanks for your attention .
Solution 1
public class Test
{
private T1 a;
private T2 b;
public Test()
{}
public void CreateFrom (int id)
{
using (var db=new WebApplicationMVCTest.Models.dbCtx())
{
a=db.T1s.Find(id);
b= db.T2s.Find(a.id2);
}
}
Solution 2:
public class DbSingleton
{
private static dbCtx instance;
private int foo;
private DbSingleton ()
{}
public static dbCtx Current
{
get
{
if (instance == null)
{
instance = new dbCtx();
}
return instance;
}
}
public static void Set (dbCtx x)
{
if (instance==null)
{
instance = x;
}
}
}
For a web project, never use a static DbContext. EF DbContexts are not thread safe so handling multiple requests will lead to exceptions.
A DbContext's lifespan should only be as long as it is needed. Outside of the first time setup cost when a DbContext is used for the first time, instantiating DbContexts is fast.
My advice is to start simple:
public ActionResult Create(/* details */)
{
using (var context = new AppDbContext())
{
// do stuff.
}
}
When you progress to a point where you learn about, and want to start implementing dependency injection applications then the DbContext can be injected into your controller / service constructors. Again, from the IoC container managing the DbContext, the lifetime scope of the Context should be set to PerWebRequest or equivalent.
private readonly AppDbContext _context;
public MyController(AppDbContext context)
{
_context = context ?? throw new ArgumentNullException("context");
}
public ActionResult Create(/* details */)
{
// do stuff with _context.
}
The gold standard for enabling unit testing would be injecting a Unit of Work pattern and considering something like the Repository pattern to make your dependencies easier to unit test.
The best advice I can give you starting out with EF and MVC is to avoid the temptation to pass Entities between the controller (server) and the UI. (views) You will come across dozens of examples doing just this, but it is a poor choice for performance, it also hides a LOT of land mines and booby traps for both performance, exceptions, and data security issues. The most important detail is that when the UI calls the controller passing what you expect will be an entity, you are not actually getting an entity, but a de-serialized JSON object cast to an entity. It is not an entity that is tracked by the DbContext handling the request. Instead, get accustomed to passing view models (serializable data containers with the data the view needs or can provide) and IDs + values where the controller will re-load entities to update the data only as needed.
Given the following scenario...
I am concerned about two things...
1) Is it okay to inject a provider into a business model object? - like I did with the Folder implementation because I want to load Sub-folders on demand.
2) Since I am injecting the DbContext in the Sql implementation of IFolderDataProvider, the context could be disposed or it could live on forever, therefore should I instantiate the context in the constructor?
If this design is incorrect then someone please tell me how should business models be loaded.
//Business model.
interface IFolder
{
int Id { get; }
IEnumerable<IFolder> GetSubFolders();
}
class Folder : IFolder
{
private readonly int id_;
private readonly IFolderDataProvider provider_;
public Folder(int id, IFolderDataProvider provider)
{
id_ = id;
provider_ = provider;
}
public int Id { get; }
public IEnumerable<IFolder> GetSubFolders()
{
return provider_.GetSubFoldersByParentFolderId(id_);
}
}
interface IFolderDataProvider
{
IFolder GetById(int id);
IEnumerable<IFolder> GetSubFoldersByParentFolderId(int id);
}
class SqlFolderDataProvider : IFolderDataProvider
{
private readonly DbContext context_;
public SqlFolderDataProvider(DbContext context)
{
context_ = context;
}
public IFolder GetById(int id)
{
//uses the context to fetch the required folder entity and translates it to the business object.
return new Folder(id, this);
}
public IEnumerable<IFolder> GetSubFoldersByParentFolderId(int id)
{
//uses the context to fetch the required subfolders entities and translates it to the business objects.
}
}
Is it okay to inject a provider into a business model object? - like I did with the Folder implementation because I want to load Sub-folders on demand.
Yes, how else would you be able to call the provider and get the data?
However, the suffix DataProvider is very confusing because it is used for the provider that you use to connect to the database. I recommend changing it to something else. Examples: Repository, Context.
Since I am injecting the DbContext in the Sql implementation of IFolderDataProvider, the context could be disposed or it could live on forever, therefore should I instantiate the context in the constructor?
It won't necessarily live on forever. You decide its life span in your ConfigureServices function when you're adding it as a service, so you can change its scope from Singleton to whatever you like. I personally set the scope of my DBContext service to Transient and I also initiate it there with the connection string:
services.AddTransient<IDbContext, DbContext>(options =>
new DbContext(Configuration.GetConnectionString("DefaultDB")));
I then open and close the database connection in every function in my data layer files (you call it provider). I open it inside a using() statement which then guarantees closing the connection under any condition (normal or exception). Something like this:
public async Task<Location> GetLocation(int id) {
string sql = "SELECT * FROM locations WHERE id = #p_Id;";
using (var con = _db.CreateConnection()) {
//get results
}
}
Is it okay to inject a provider into a business model object
Yes if you call it "business" provider :). Actually do not take too serious all this terminology "inject", "provider". Till you pass (to business model layer's method/constructor) interface that is declared on business model layer (and document abstraction leaks) - you are ok.
should I instantiate the context in the constructor?
This could be observed as an abstraction leak that should be documented. Reused context can be corrupted or can be shared with another thread and etc -- all this can bring side effects. So developers tend to do create one "heavy" object like dbContext per "user request" (that usually means per service call using(var context = new DbContext()), but not always, e.g. Sometimes I share it with Authentication Service Call - to check is the next operation allowed for this user). BTW, DbContext is quite quick to create so do not reuse it just for "optimization".
I am currently in the process of converting a large web service to use the repository pattern and dependency injection. We are expanding our team and the benefits of reliable unit testing outweighs the effort required to refactor the code.
I have chosen Ninject as my framework based on the recommendation of a colleague and have begun refactoring my code. This has involved creating a "Common" project that contains the objects themselves, a Repository.Database project to contain the data access logic, and a web service that uses both. I have used convention based mapping so that IPersonRepository should map to my concrete PersonRepository class.
I am currently taking the approach of creating a "Repository" property on each class with the [Inject] attribute, then replacing my constructors to use said repository, but have run into my first stumbling block and am not convinced I am doing things the right way. Before I started all this, I would instantiate an object like so:
var p = new Person(ID);
And using the format I suggested, my class looks something like this:
[Inject]
public IPersonRepository Repository { get; set; }
public string Name;
public Person(int ID)
{
// This feels wrong
var p = Repository.Get(ID);
Name = p.Name;
}
You can probably see my conundrum. How can I use a constructor without having to return a new object from the repository and then map each field to my current object? I can't replace "this", and while I could use something like AutoMapper to map each field in one go, it feels like I am doing something inherently wrong here.
I could use a static method instead of an injector:
[Inject]
public static IPersonRepository Repository { get; set; }
public string Name;
public static Person GetByID(int ID)
{
return Repository.Get(ID);
}
But as you can see it requires making Repository static, and it feels like I should be using a constructor rather than a static "GetByID" method. That could just be because I am so used to using a constructor.
Alternatively I can pass the Repository into the Person constructor, but again, it feels messy to do that every time I instantiate a Person in code.
What I am trying to achieve is to have my existing WCF project load all of its data using one repository, and for my Unit Test project to load all its data using another. I don't want to have to pass concrete implementations of IPersonRepository in either. Is this achievable and even recommended?
Your entities should not need to know anything about where or how they are stored. The idea of the repository pattern is to take the responsibility of persistence away from the business logic. Practically this means you would set up your service as follows:
Create separate repositories for each "top level" entity
Inject the repositories into your web service/controller/business object
Define your entities as regular business objects with state and behavior
have the web service etc use the repository to fetch the entities as needed via ID
You should't need to call a constructor with an ID from the business logic...that's a bad pattern
You would still use the constructor to instantiate a new entity that you would then submit to the repository e.g. personRepository.Add(new Person("Bob"))
This would then have the added benefit of making your web service testable by injecting a mocked repository and not having to worry about how the entities would get retrieved in your code itself.
I've created a small helper class : "EntityResolver" which implements the "IValueResolver" interface which was introduced recently in AutoMapper. This helper class can retrieve an entity from the repository when an Id is supplied.
1) AutoMapper configuration to map a ViewModel to an Entity is defined as follows:
Mapper.CreateMap<EmployeeVM, Employee>()
.ForMember(e => e.EmployeeNumber, opt => opt.MapFrom(vm => vm.Number))
// Other propeties omitted
.ForMember(e => e.Company, opt => opt.ResolveUsing<EntityResolver<Company>>().FromMember(vm => vm.CompanyId))
;
2) Code for the EntityResolver
public class EntityResolver<TEntity> : IValueResolver where TEntity : class, IEntity, new()
{
public ResolutionResult Resolve(ResolutionResult source)
{
return source.New(ResolveObject(source));
}
private object ResolveObject(ResolutionResult source)
{
if (!source.Context.Options.Items.ContainsKey("Services")) return null;
var services = (List<object>)source.Context.Options.Items["Services"];
var item = services.FirstOrDefault(s => s is IBaseService<TEntity>);
if (item == null) return null;
var id = (long)source.Value;
if (id <= 0) return null;
var service = (IBaseService<TEntity>)item;
return service.GetById(id);
}
}
3) When mapping the ViewModel to an Entity, I supply additional IMappingOperationOptions
Mapper.Map<TEntity>(viewModel, opt => opt.Items["Services"] = GetServices());
4) The GetServices method just returns all services needed to resolve the entities used in the Employee object.
protected override List<object> GetServices()
{
var services = base.GetServices();
services.Add(_companyService);
services.Add(_functionService);
services.Add(_subfunctionService);
services.Add(_countryService);
return services;
}
For more details see my test project.
I am using a Unit of Work pattern in my mvc 3 app with Ninject. I have run into a problem where i'm having difficulty solving it without using new or service location of some kind.
I am using an abstract base model called MyModel which has 2 concrete subclasses MyModel1 and MyModel2. These need to get sent to the view based on a value set in the users record.
public class MyController : Controller
{
private IUnitOfWork _unitOfWork;
public MyController(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; }
...
public ActionResult MyMethod() {
var user = _unitOfWork.Get(user)
if (user.myprop == somevalue)
{
return View(new MyModel1());
}
return View(new MyModel2());
}
This works fine (although I don't like it, it's simple and works. The problem is that using new is an anti-pattern when using Dependancy Injection. Additionally, I now want the models to initialize themselves (from the database) so I need to inject the IUnitOfWork into the constructor of the models. I could, of course do this:
if (user.myprop == somevalue)
{
return View(DependancyResolver.Current.GetService(typeof(MyModel1)));
}
But Service Location is also an anti-pattern.
Any suggestions on how to solve this?
Using new is not an anti pattern for DI if used correctly. There is absolutely no problem to use new to create data containers such as view models.
But it is an anti pattern for MVC applications to have logic or data retrieving code in your view models so that they need dependencies. All this stuff belongs outside into the controller or some services. The data is assigned preformatted to the view model from outside.
Additionally, I now want the models to initialize themselves (from the
database) so I need to inject the IUnitOfWork into the constructor of
the models
No. You should not pass any models to your views. You pass VIEW MODELS only. View models are dumb. They only contain preformatted data for the view to display. If you used AutoMapper for example you could have externalized this into the mapping layer and your controller could become:
public ActionResult MyMethod() {
var user = _unitOfWork.Get(user)
var userViewModel = Mapper.Map<User, UserViewModel>(user);
return View(userViewModel);
}
I am looking at depency injection, I can see the benefits but I am having problems with the syntax it creates. I have this example
public class BusinessProducts
{
IDataContext _dx;
BusinessProducts(IDataContext dx)
{
_dx = dx;
}
public List<Product> GetProducts()
{
return dx.GetProducts();
}
}
The problem is that I don't want to write
BusinessProducts bp = new BusinessProducts(dataContextImplementation);
I would continue to write
BusinessProducts bp = new BusinessProducts();
because I feel the first alternative just feels unatural. I dont want to know what the BusinessProduct "depends" on to get the products, also I feel it makes my code more unreadable.
Is there any alternatives to this approach as I would like to keep my original syntax for creating objects but I would like to still be able to fake the dependencies when unit testing or is it this dependecy injection frameworks can do for me?
I am coding in c# but alternatives from other languages is welcome
I use a factory for my context and inject it, providing a suitable default if the provided factory is null. I do this for two reasons. First, I use the data context as a unit of work scoped object so I need to be able to create them when needed, not keep one around. Second, I'm primarily using DI to increase testability, with decoupling only a secondary consideration.
So my business products class would look like:
public class BusinessProducts
{
private IDataContextFactory DataContextFactory { get; set; } // my interface
public BusinessProducts() : this(null) {}
public BusinessProducts( IDataContextFactory factory )
{
this.DataContext = factory ?? new BusinessProductsDataContextFactory();
}
public void DoSomething()
{
using (DataContext dc = this.DataContextFactory().CreateDataContext())
{
...
}
}
An alternative to this would be to make the factory property publicly settable and inject an alternate factory by setting the property. Either way if you want to keep the null constructor, you'll need to provide a default.
You can create a factory. DI containers are best for wirings that happen at setup-time - not at runtime (As this looks to be a case of). Factories can be implemented in different ways, depending on how pluggable it needs to be, and how many places you need to use it.
I would usually have an empty constructor which uses a solid instance( or an instances created by IoC), amd one with DI. i.e.
public class BusinessProducts
{
IDataContext _dx;
BusinessProducts()
{
_dx = new SolidDataContext();
}
BusinessProducts(IDataContext dx)
{
_dx = dx;
}
}
This way you can use DI for overriding the default instance in unit testing testing.
Your feelings, while valid, are misplaced.
The Dependency Injection pattern is a direct application of the Inversion of Control principle.
This means that, instead of your class controlling the instances of other classes it consumes, that relationship is inverted and the dependencies are provided to it.
As such, your classes naturally expose their dependencies via constructor arguments or properties. Showing disdain for this structure says you haven't truly grokked the pattern.
There are two distinct cases here:
In production code you will never write
new BusinessProducts(dataContextImplementation)
because dependency injection will normally be creating the full object hierarchy for you. This is the "viral" nature of dependency injection patterns, they tend to take over full control of your service creation.
In unit test code you will normally be creating this yourself, but quite often you will be supplying a mock object or a stub implementation of dataContextImplementation. So normally you will be injecting an object that does not have a large number of subsequent dependencies.
http://springframework.net/ and http://structuremap.sourceforge.net/Default.htm are probably the mostly used DI frameworks for .NET based languages and will both do what you need.
Generally the framework itself will have the logic to build up the entire object tree. For example, instead of
new SomeObjectO(diContext)
you would call the framework like this:
DIFramework.GetNew<SomeObjectO>();
or
DIFramework.Get<SomeObject>();
Another interesting framework to take a look at if you would like to learn about DI and the process is Microsoft's Unity and Object Builder projects.
If you really do not like injecting this instance in the constructor, you might try to use the CommonServiceLocator with your favourite compatible .NET depedency injection framework. This would allow you to write code like this:
public class BusinessProducts
{
IDataContext _dx;
BusinessProducts()
{
_dx = Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<IDataContext>();
}
public List<Product> GetProducts()
{
return dx.GetProducts();
}
}
However, please beware that this is not what most people would expect when they know that you use a dependency injection framework. I think that it is much more common to use a dependency injection framework and letting it create all objects for you.
BusinessProducts bp = Microsoft.Practices.ServiceLocation.ServiceLocator.Current.GetInstance<BusinessProducts>();
If you would like to avoid the dependeny injection framework path, using a factory is probably the best way to go.
There's a technique called poor man's DI that looks like this
public class BusinessProducts
{
IDataContext _dx;
BusinessProducts() : this(new DataContext()) {}
BusinessProducts(IDataContext dx)
{
_dx = dx;
}
public List<Product> GetProducts()
{
return dx.GetProducts();
}
}
This is not ideal since it ties you to the implementation but its a good stepping stone towards decoupled code. this is similar to #tvanfosson but a lot simplier.
I second the recommendation for Windsor
My code will reference Microsoft Unity but I am sure it is pretty applicable to all DI frameworks. If you're using DI correctly you never need to call new BusinessObject(new dataContext) the DI association will handle it all for you.
My example will be a little bit long since I will paste in some code I use for running a Model View Presenter website fully DI loaded by Unity. (If you want the full source check out my blog and download it from my Assembla SVN server)
Load the container (can be in code like I prefer or using configuration)
protected void Application_Start(object sender, EventArgs e)
{
Application.GetContainer()
// presenters / controllers are per request
.RegisterType<IEmployeeController, EmployeeController>(new ContextLifetimeManager<IEmployeeController>())
//Data Providers are Per session
.RegisterType<IEmployeeDataProvider, EmployeeDataProvider>(new SessionLifetimeManager<IEmployeeDataProvider>())
//Session Factory is life time
.RegisterType<INHibernateSessionManager, NHibernateSessionManager>(new ContainerControlledLifetimeManager());
}
Custom HTTP module calls Unity BuildUp Method for each page during the OnPreRequest invocation.
private static void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
var handler = HttpContext.Current.Handler;
HttpContext.Current.Application.GetContainer().BuildUp(handler.GetType(), handler);
// User Controls are ready to be built up after the page initialization is complete
var page = HttpContext.Current.Handler as Page;
if (page != null)
{
page.InitComplete += OnPageInitComplete;
}
}
Page container presenter decorated with [Dependency] attribute
public partial class Employees : Page, IEmployeeView
{
private EmployeePresenter _presenter;
[Dependency]
public EmployeePresenter Presenter
{
set
{
_presenter = value;
_presenter.View = this;
}
}
}
Presenter with InjectionConstructor method
public class EmployeePresenter : Presenter<IEmployeeView>
{
private readonly IEmployeeController _controller;
[InjectionConstructor]
}
public EmployeePresenter(IEmployeeController controller)
{
_controller = controller;
}
Controller follows suit
public class EmployeeController : IEmployeeController
{
private readonly IEmployeeDataProvider _provider;
[InjectionConstructor]
public EmployeeController(IEmployeeDataProvider DataProvider)
{
_provider = DataProvider;
}
}
Same with provider
public class EmployeeController : IEmployeeController
{
private readonly IEmployeeDataProvider _provider;
[InjectionConstructor]
public EmployeeController(IEmployeeDataProvider DataProvider)
{
_provider = DataProvider;
}
}
Lastly the session manager, which contains only a regular constructor.
public class NHibernateSessionManager : INHibernateSessionManager
{
private readonly ISessionFactory _sessionFactory;
public NHibernateSessionManager()
{
_sessionFactory = GetSessionFactory();
}
}
So what happens when a page request is started the BuildUp() method is called on the page by the HttpModule. Unity then sees the Property marked with the Dependency attribute and will check it's container to see if inside it exists an EmployeePresenter object.
Since there is no such object in the container it will then try to create an EmployeePresenter. Upon inspection to create the class it sees inside the Presenter it requires a constructor that needs a IEmployeeController injected into it. Since the container actually has a manager for the controller it will see if an instance of it exists in the container which on the beginning of the page request doesn't exist, so it will go to instantiate the controller.
Unity will then see the controller requires a IEmployeeDataProvider injected into it, and it will continue on this process until it finally gets to the point where the Provider needs the session manager injected. Since the session manager has no more need for injection Unity will then create an instance of the session manager store it in the container for it's given ContainerLifeTimeManager, inject it into the Provider and store that instance, and so on down to where it finished creating a EmployeePresenter dependency for the page.
you can also look at windsor for IoC .