I'm making a start on an MVC project, having gone through the MvcMusicStore tutorial. I'm trying to get my head around how the POCO-generated data/entity context is intended to be stored.
In the samples, the controller generates a copy of the entity context, and all operations complete there:
MusicStoreEntities storeDB = new MusicStoreEntities();
//
// GET: /Store/
public ActionResult Index()
{
// Retrieve list of Genres from database
var genres = from genre in storeDB.Genres
select genre.Name;
[...]
If I'm to split my solution into layers, what is the standard practice (or key options) for retaining the context? Do I generate it in the controller, and pass it to the repository, or is it possible for the repository to keep a general-use copy?
I understand that the the above would be necessary to use the Unit of Work pattern.
My layers are:
Data (edmx file)
Entities (Generated from POCO)
Repository
Mvc web app
My other questions:
- What is the overhead of generating the context?
- As there is no .Close(), and it doesn't implement IDisposable, is the ObjectContext behind it generating individual connections, connection pooling, sharing a single instance?
- Is it possible to lock an ObjectContext if it's passed around between layers / operations too much?
Thanks in advance.
I don't want to go into too much detail/code here, so i'll just mention some points:
Your controller can work with multiple repositories
There should be one repository per aggregate root
Controller work amongst multiple repositories are made possible by Unit of Work
Use a DI container to handle lifetime management of Unit of Work (which is actually the context)
Do not use singletons for the Context, let the DI container instantiate/dispose of the context per HTTP request
I create a single repository for each controller and put my context in there. The rules I follow are that the repository handles anything that I might want to mock (not really the definition of repository, but it works for me). The repository can call other repositories if necessary, but the controller shouldn't have to know about it. The Context is an instance property of the repository and is created on demand (I haven't taken the leap into IOC yet). If the repository calls another repository, it passes the Context instance.
It looks a little like this...
public class MyController : Controller
{
public IMyControllerRepository Repository { get; set; }
public ActionResult MyAction(int id)
{
var model = Repository.GetMyModel(id);
return View(model);
}
}
public class MyControllerRepository : IMyControllerRepository
{
public MyContext Context { get; set; };
public MyModel GetMyModel(int id)
{
return (from m in Context.MyModels
where m.ID = id
select m).SingleOrDefault();
}
}
Related
I am building a Web application with ASP.NET and I have made two separate projects within one solution of which one is the ASP.NET project and the other one a 'Console Application' called data layer. In the data layer I have connected it with my local db (ADO.NET entity framework database first).
My question is, I want my DbContext class to be inaccessible in the controllers within my ASP.NET project. Currently it is still reachable by just 'using data layer'. I have a folder in my ASP.NET with builder classes and they can reach the DbContext, I only want the builders to reach my DbContext. So in my controller I only want to use my builders to do something with the DbContext.
Example of how I want it:
public ActionResult Index()
{
return View(new ExampleBuilder().GetListFromDb());
}
And not (this must be forbidden and inaccessible within my project):
private DbContext db = new DbContext();
public ActionResult Index()
{
return View(db.SomeModel.ToList());
}
Does anyone have a good solution for this?
You can use following project structure
Web (Depends on Data.Repositories and Common)
Data.Repositories (Depends on Data.Model and Common) - here you implement repositories that use your EntityFramework context from Data.Model.
Data.Model (Depends on Common) - put your EntityFramework context class here, but all the models should go into Common to make them available for all projects.
Common - your EntityFramework models and everything else that needs to be accessible everywhere e.g. exceptions, utils.
Basically your repository methods would look like that:
public Common.User GetUserByEmail(string email)
{
using (var context = new Data.Model.MyContext())
{
return context.Users.FirstOrDefault(user => user.Email == email);
}
}
Your web doesn't have a reference to Data.Model and it will not be able to use your context class directly. It will have to go through the Repositories abstraction layer.
But how do you use it?
I have a Code First project set up, and trying out some stuff with this new EF6. Reading all kinds of posts/blogs from at least 2 years old about EF4/5. But nothing whatsoever about EF6.
Let's say I have these entities:
public DbSet<Person> Persons { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<Invoice> Invoices { get; set; }
Do I still need to create repositories for each entity? Or would a class suffice with some methods to do some custom calculations aside from CRUD?
I know that this line:
kernel.Bind<MyDbContext>().ToSelf().InRequestScope();
Would suffice for DI, and that it will inject via constructor to upper layer classes where applicable.
The project has a class library and a web project asp.net-mvc. Where the class lib project contains my entities and has Migrations enabled.
Any light on this matter is really appreciated.
I've added a Repository layer on top of EF (which utilizes both Repository and UoW patterns inherently in its construction) in a couple of projects, and I've done that with one class that utilizes generics so that I only needed one file for all of my entities. You can decide if you want to do it or not, but I've found it useful in my projects.
My repositories have typically started out like what I've shown below, following up with more extension methods if/when I come across a need for them (obviously I'm not showing all of them, that's up for you to decide how to implement your repository).
public class Repository<T> : IRepository<T> where T : class
{
protected IDbContext Context;
protected DbSet<T> DbSet { get { return Context.Set<T>(); } }
public Repository(IDbContext context = null)
{
Context = context ?? new DbContext();
}
public void Add(T newRecord)
{
DbSet.Add(newRecord);
}
public void Update(T record)
{
var entry = Context.Entry(record);
DbSet.Attach(record);
entry.State = EntityState.Modified;
}
public void Remove(T record)
{
Context.Entry(record).State = EntityState.Deleted;
DbSet.Remove(record);
}
public IQueryable<T> Where(Expression<Func<T, bool>> predicate)
{
return DbSet.Where(predicate);
}
public bool Contains(Expression<Func<T, bool>> predicate)
{
return DbSet.Count(predicate) > 0;
}
public int Count(Expression<Func<T, bool>> predicate)
{
return DbSet.Count(predicate);
}
public int Save()
{
return Context.SaveChanges();
}
}
I've used repositories for 2 main reasons:
Unit testing. Doing this pattern allows me to fake the underlying data without having to have bad data in my database. All I need to do is simply create another implementation of IRepository that uses an in-memory list as its data source, and I'm all set for my pages to query that repository.
Extensibility. A fair number of times I've put in some methods into my repository because I found myself constantly doing the same logic with queries in my controllers. This has been extremely useful, especially since your client-side code doesn't need to know how it's doing it, just that it is doing it (which will make it easier if you need to change the logic of one file vs. multiple files).
This not all of it, obviously, but that should be enough for this answer. If you want to know more on this topic, I did write a blog post on it that you can find here.
Good luck on whatever you decide to do.
Entity Framework in itself can be considered a Repository. It facilitates work with data, in this case a database. This is all that a Repository does.
If you want to build another Repository on top of what EF provides, it is completely up to you - or to your business rules.
Many complex projects uses 2-3 layers of repositories with web services between. The performance is lower but you gain on other plans like security, resilience, separation of concerts, etc.
Your company might decide that it's in their best interest to never access data directly from front-end projects. They might force you to build a separate web-service project, which will be accessible only from localhost. So you will end up having EF as Repository in the webservice project. On the front-end side you will obviously need to build another Repository which will work with the web-service.
It also depends a lot of your project. If it's a small project it really it's overkill to build a second Repository on top of EF. But then again, read above. Nowadays security matters a lot more than performance.
To be politically correct I'm including the comment made by Wiktor Zychla:
"DbSet is a repository and DbContext is a Unit of Work. "Entity Framework is a Repository" could lead to unnecessary confusion."
I've been reading up on Dependency Incection, UnitOfWork and IRepository patterns, and I intend to implement them all as I go along. But it's all a lot to take in at once. Right now I just want to make sure about some basic things, and that I'm not missing anything crucial that could impact my application.
The application is rather small and there will be no more than 10 simultaneous users at any given point.
The AdressRegDataContext is the dbml generated (using Visual Studio Add -> Linq to SQL classes).
My question concern the adding of the second controller below:
Are there any problems creating a new repository in each controller like this?
To me it feels like two users would have two different contexts if they are using the application at the same time. Or do the datacontext handle that for me? A singleton repository makes sense theoretically, but I've read that that's a big nono so I won't do that.
I have a repository that I use:
Repository
namespace AdressReg.Models
{
public class AdressRegRepository
{
private AdressRegDataContext db = new AdressRegDataContext();
// Return person by id
public Person GetPerson(int id)
{
return db.Persons.SingleOrDefault(p => p.id == id);
}
// Return student by id
public Student GetStudent(int id)
{
return db.Students.SingleOrDefault(s => s.id == id);
}
}
}
So far I've only been using the one controller:
HomeController
namespace AdressReg.Controllers
{
public class HomeController : Controller
{
AdressRegRepository repository = new AdressRegRepository();
// GET: /Home/Person
public ActionResult Person(int id)
{
PersonView view = new PersonView();
view.person = repository.GetPerson(id);
return View(view);
}
}
}
But I was planning on adding another:
EducationController
namespace AdressReg.Controllers
{
public class EducationController: Controller
{
AdressRegRepository repository = new AdressRegRepository();
// GET: /Education/Student
public ActionResult Student(int id)
{
StudentView view = new StudentView();
view.student = repository.GetStudent(id);
return View(view);
}
}
}
Yes they are. First of all that's not a 'true' repository, that is a useless abstraction on top of EF, you can ditch it. A repository should return busines or app objects not EF entities. For querying purposes it should return at least some bits (if not all ) of the view model. So, it should return a PersonView or a StudentView. These are guideliness not the absolute truth or rules, but you really need to be aware of the purpose of a design pattern, in this case the Repository. And your code shows you haven't understood it yet.
In your app, the repo doesn't do anything useful, so use the ORM directly, it's much simpler.
Your controllers are tightly coupled to a specific concrete repository. The point is you should define an abstraction and pass that as a dependency in the constructor. Something like
// a better name is needed, this would be a query repository
public interface IAddressesRegRepository
{
StudentView Get(int it);
}
public class MyController:Controller
{
IAddressesRegRepository _repo;
public MyController(IAddressesRegRepository repo)
{
_repo=repo;
}
public ActionResult Student(int id)
{
StudentView view = _repo.GetStudent(id);
return View(view);
}
}
As you see, the controller now depends on an abstraction, the DI Container will inject a concrete implementation when the controller is created. It will allow you to mock repositories and to have multiple implementations. Same approach is for everything you want to use in the controller.
About repositories, I do prefer to have different business/ query repositories (though nowadays I'm using query handlers) i.e I don't put querying behaviour on a domain repository unless it's needed by the business layer itself.
For strictly querying, it's much straight forward to use EF or if your queries are ugly or want to change implementation later, use a query object/ repository/service/handler (call it however you want) that will construct the view model from persistence. The point is to keep the persistence details (ORM, EF Entites) in the DAL, your UI shouldn't know about them. In your example, the UI knows about EF entites.
Once again, what I've said are guidelines, when you get more experienced you'll know when to bend (break) them without nasty side effects.
I have the following problem - or rather, an urgent need for valuable advice - with Microsoft MVC. A certain action from the client leads to the creation of:
A remark in the table Remarks
An entry in the table for HourRegistrations
An entry in the changelog for Tickets
I use a service layer for business actions and repositories for CRUD actions. The problem is that I at times need to connect objects from different DataContexts so I suppose I use a flawed design. Recently we have started to remove all business logic from our controllers and repositories and this is one of the first things I run into.
Example:
BLogic.AddRemarks(Ticket t, ...)
{
Remark r = _remarksRepository.Create();
r.Ticket = t;
_remarksRepository.Add(r);
_remarksRepository.Save();
}
This triggers kBOOM since the Ticket is fetched in the controller using the repository. So Remark r and Ticket t do not share the same data context.
I can alter the signature of the method and provide an int TicketId, but that doesn't feel right. Besides, I then get similar problems further down the line.
My repositories are created at the constructor of the service class. Perhaps I must create them at the start of a method? Even then, I must often transfer Ids instead of the true objects.
My suggestion is to use dependeny injection (or inversion of control - depends how would you like to call it). I use myself castle windor. Really simple to integrate with mvc.net. read more
When IoC is up and running create ContextManager. Somethig like this:
public class ContextManager : IContextManager
{
private XContext context;
public XContext GetContext()
{
return context ?? (context = XContext.Create());
}
}
Set IContextManager lifestyle as perwebrequest and you got yourself context that you can access from repositories and services. and it's same per one request.
EDIT
You also have to create your own controllerFactory
then you can use your services and repositories like this:
public class MyController : Controller
{
public ISomeService SomeService { get; set; }
public IContextManager ContextManager { get; set; }
...
}
You dont have to create new instances for services and repositories and you can manage those objects lifestyle from configuration. Most reasonable would be singleton
In OOP Design Patterns, what is the difference between the Repository Pattern and a Service Layer?
I am working on an ASP.NET MVC 3 app, and am trying to understand these design patterns, but my brain is just not getting it...yet!!
Repository Layer gives you additional level of abstraction over data access. Instead of writing
var context = new DatabaseContext();
return CreateObjectQuery<Type>().Where(t => t.ID == param).First();
to get a single item from database, you use repository interface
public interface IRepository<T>
{
IQueryable<T> List();
bool Create(T item);
bool Delete(int id);
T Get(int id);
bool SaveChanges();
}
and call Get(id). Repository layer exposes basic CRUD operations.
Service layer exposes business logic, which uses repository. Example service could look like:
public interface IUserService
{
User GetByUserName(string userName);
string GetUserNameByEmail(string email);
bool EditBasicUserData(User user);
User GetUserByID(int id);
bool DeleteUser(int id);
IQueryable<User> ListUsers();
bool ChangePassword(string userName, string newPassword);
bool SendPasswordReminder(string userName);
bool RegisterNewUser(RegisterNewUserModel model);
}
While List() method of repository returns all users, ListUsers() of IUserService could return only ones, user has access to.
In ASP.NET MVC + EF + SQL SERVER, I have this flow of communication:
Views <- Controllers -> Service layer -> Repository layer -> EF -> SQL Server
Service layer -> Repository layer -> EF This part operates on models.
Views <- Controllers -> Service layer This part operates on view models.
EDIT:
Example of flow for /Orders/ByClient/5 (we want to see order for specific client):
public class OrderController
{
private IOrderService _orderService;
public OrderController(IOrderService orderService)
{
_orderService = orderService; // injected by IOC container
}
public ActionResult ByClient(int id)
{
var model = _orderService.GetByClient(id);
return View(model);
}
}
This is interface for order service:
public interface IOrderService
{
OrdersByClientViewModel GetByClient(int id);
}
This interface returns view model:
public class OrdersByClientViewModel
{
CientViewModel Client { get; set; } //instead of ClientView, in simple project EF Client class could be used
IEnumerable<OrderViewModel> Orders { get; set; }
}
This is interface implementation. It uses model classes and repository to create view model:
public class OrderService : IOrderService
{
IRepository<Client> _clientRepository;
public OrderService(IRepository<Client> clientRepository)
{
_clientRepository = clientRepository; //injected
}
public OrdersByClientViewModel GetByClient(int id)
{
return _clientRepository.Get(id).Select(c =>
new OrdersByClientViewModel
{
Cient = new ClientViewModel { ...init with values from c...}
Orders = c.Orders.Select(o => new OrderViewModel { ...init with values from o...}
}
);
}
}
As Carnotaurus said the repository is responsible for mapping your data from the storage format to you business objects. It should handle both how to read and write data(delete, update too) from and to the storage.
The purpose of service layer on the other hand is to encapsulate business logic into a single place to promote code reuse and separations of concerns. What this typically means for me in practice when building Asp.net MVC sites is that I have this structure
[Controller] calls [Service(s)] who calls [repository(ies)]
One principle I have found useful is to keep logic to a minimum in controllers and repositories.
In controllers it is because it helps keeping me DRY. It's very common that I need to use the same filtering or logic somewhere else and if I placed it in the controller I can't reuse it.
In repositories it is because I want to be able to replace my storage(or ORM) when something better comes along. And if I have logic in the repository I need to rewrite this logic when I change the repository. If my repository only returns IQueryable and the service does the filtering on the other hand, I will only need to replace the mappings.
For example I recently replaced several of my Linq-To-Sql repositories with EF4 and those where I had stayed true to this principle could replaced in a matter of minutes. Where I had some logic it was a matter of hours instead.
The accepted answer (and upvoted hundreds of time) has a major flaw. I wanted to point this out in the comment but it will just get buried down there in 30 something comments so pointing out here.
I took over an enterprise application which was built that way and my initial reaction was WTH? ViewModels in service layer? I did not want to change the convention because years of development had gone into it so I continued with returning ViewModels. Boy it turned into a nightmare when we started using WPF. We (the team of devs) were always saying: which ViewModel? The real one (the one we wrote for the WPF) or the services one? They were written for a web application and even had IsReadOnly flag to disable edit in the UI. Major, major flaw and all because of one word: ViewModel!!
Before you make the same mistake, here are some more reasons in addition to my story above:
Returning a ViewModel from the service layer is a huge no no. That's like saying:
If you want to use these services you better be using MVVM and here is the ViewModel you need to use. Ouch!
The services are making the assumption they will be displayed in a UI somewhere. What if it is used by a non UI application such as web services or windows services?
That is not even a real ViewModel. A real ViewModel has observability, commands etc. That is just a POCO with a bad name. (See my story above for why names matter.)
The consuming application better be a presentation layer (ViewModels are used by this layer) and it better understand C#. Another Ouch!
Please, don't do that!
Repository layer is implemented to access the database and helps to extend the CRUD operations on the database. Whereas a service layer consists of the business logic of the application and may use the repository layer to implement certain logic involving the database. In an application, it is better to have a separate repository layer and service layer. Having separate repository and service layers make the code more modular and decouple the database from business logic.
Usually a repository is used as scaffolding to populate your entities - a service layer would go out and source a request. It is likely that you would put a repository under your service layer.