Difference between Repository and Service Layer? - asp.net-mvc

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.

Related

Creating new repositories with each controller

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.

better organise database operation codes in mvc

I am new to .net mvc ,and here is my situation, in mvc solution, I have data modal and reposity,also have ioc container, when comes to operate data operation,should I put all my logical code in the controller?or there are any better way?
public ActionResult SomeOperate(Person person)
{
var reposity = _kernel.Get<IReposity<Person>>();
//what about if there are many database operation logical based on my generic reposity,should I put them all here?
return RedirectToAction("SomeWhere");
}
EDIT1
my generic reposity have already support basic database operations such as add,update,remove,query transaction
By default, the controller can contain business logic (and its okay). But as your application grows in size, you start doubting whether the controller should be responsible for containing the business logic.
In a more advance architecture, the Controller only acts as a "Coach" and let players do the job. In other words, the controller only worries about who should do what. Hence the name controller.
The Service Layer
The Service Layer is just a collection of classes created for one purpose, to encapsulate your business layer, moving the logic away from the controller.
See my example below for a basic implementation of a service.
Service
public class ProductService
{
private IProductRepository productRepository;
public ProductService(IProductRepository productRepository)
{
this.productRepository = productRepository;
}
public IEnumerable<Product> ListProducts()
{
return this.productRepository.ListProducts();
}
public void CreateProduct(Product productToCreate)
{
// Do validations here.
// Do database operation.
this.productRepository.Create(productToCreate);
}
}
Controller
// Controller
public class ProductController : Controller
{
private ProductService productService;
// If you are wondering how to instantiate this
// controller, see the ninject tutorial
// http://www.codeproject.com/Articles/412383/Dependency-Injection-in-asp-net-mvc4-and-webapi-us
public ProductController(ProductService productService)
{
this.productService = productService;
}
public ActionResult Index()
{
IEnumerable<Product> products = this.productService.ListProducts();
return View(products);
}
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Product productToCreate)
{
if(!ModelState.IsValid)
{
return View();
}
this.productService.Create(productToCreate);
return RedirectToAction("Index");
}
The full tutorial straight from Microsoft: http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validating-with-a-service-layer-cs
UPDATE
Why use a service layer
https://softwareengineering.stackexchange.com/questions/162399/how-essential-is-it-to-make-a-service-layer
Service per Model/Entity
With regards to the number of service per model, there is no absolute rule. Most of the time it can scale to one-to-one and sometimes one-to-many (referred service per module)
The number routines in a single service class depends on the number of operations in the UI, meaning if there is no delete button anywhere in the system then there shouldn't be a delete method anywhere in your code. In other words, CRUD should only apply when needed.
Service per Module
Sometimes a service can scale to multiple models, given there is an operation that requires you to updated multiple models. This is sometimes referred as "service per module", this is when a service does not represent a model but rather an operation.
RetireService
- RetireEmployee(User user)
MailingService
- SendWeeklyMails()
Services and Interfaces
Most of the time, interfaces are not required for a service layer. The only time that they are usually for the following reasons:
Large team (5 or more)
Large system
Heavy test driven development.
This link extends much on this subject:
https://softwareengineering.stackexchange.com/questions/159813/do-i-need-to-use-an-interface-when-only-one-class-will-ever-implement-it
The Single-Responsibility Principle would indicate that you should identify one responsibility for each class, and avoid putting logic into the class that doesn't pertain to that responsibility.
If this is just an exercise in learning technologies, or a small project, then you're probably safe putting most of your Entity manipulations and business logic in the individual controller actions. If this project is likely to grow, and need to be maintained by various people over time, you're probably better off defining an N-Tier architecture right off the bat.
How you do this will depend somewhat on personal preference and the nature of your project, but a popular approach is to create a "Service" or "Manager" layer where all of your business logic resides. Then the various controller actions invoke the actions on that layer, transform them into ViewModel objects, and pass them off to the views. In this architecture, Controllers end up begin very light-weight, and are focused mostly on transforming requests into service calls and composing the data that the Views will need to render.
Many people feel that the ORM (e.g. Entity Framework) represents the "data access layer," and they don't see a need to create an additional layer beyond the service layer. Other people create individualized classes to hold the queries and commands to Entity Framework, and the Service layer leverages these various other classes.

Design of Service Layer and Repositories in Microsoft MVC

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

Service Layer are repeating my Repositories

I'm developing an application using asp.net mvc, NHibernate and DDD. I have a service layer that are used by controllers of my application. Everything are using Unity to inject dependencies (ISessionFactory in repositories, repositories in services and services in controllers) and works fine.
But, it's very common I need a method in service to get only object in my repository, like this (in service class):
public class ProductService {
private readonly IUnitOfWork _uow;
private readonly IProductRepository _productRepository;
public ProductService(IUnitOfWork unitOfWork, IProductRepository productRepository) {
this._uow = unitOfWork;
this._productRepository = productRepository;
}
/* this method should be exists in DDD ??? It's very common */
public Domain.Product Get(long key) {
return _productRepository.Get(key);
}
/* other common method... is correct by DDD ? */
public bool Delete(long key) {
usign (var tx = _uow.BeginTransaction()) {
try
{
_productRepository.Delete(key);
tx.Commit();
return true;
} catch {
tx.RollBack();
return false;
}
}
}
/* ... others methods ... */
}
This code is correct by DDD ? For each Service class I have a Repository, and for each service class need I do a method "Get" for an entity ?
Thanks guys
Cheers
Your ProductService doesn't look like it followed Domain-Driven Design principles. If I understand it correctly, it is a part of Application layer between Presentation and Domain. If so, the methods on ProductService should have business meaning with regard to products.
Let's talk about deleting products. Is it as simple as executing delete on the database (NHibernate, or whatever?) I think it is not. What about orders which reference the to-be-deleted product? And so on and so forth. Btw, Udi Dahan wrote a great article on deleting entities.
Bottom line is, if your application is so simple that services do really replicate your repositories and contain only CRUD operations, you probably shouldn't do DDD, throw away your repositories and let services operate on entities (which would be simple data containers in that case).
On the other hand, if there is a complicated behavior (like the one with handling 'deleted' products), there is a point in going DDD path and I strongly advocate doing so.
PS. Despite which approach (DDD or not) you will eventually take I would encourage you to use some Aspect Oriented Programming to handle transaction and exception related stuff. You would end up with way to many methods such as DeleteProduct with same TX and exception handling code.
That looks correct from my perspective. I really didn't like repeating service and repository method names over and over in my asp.net MVC project, so I went for a generic repository approach/pattern. This means that I really only need one or two Get() methods in my repository to retrieve my objects. This is possible for me because I am using Entity Framework and I just have my repository's get() method return a IQueryable. Then I can just do the following:
Product product = from p in _productRepository.Get() where p.Id == Id select p;
You can probably replicate this in NHibernate with linq -> NHibernate.
Edit: This works for DDD because this still allows me to interchange my DAL/repositories as long as the data library I am using (Nhibernate, EF, etc..) supports IQueryable.
I am not sure how to do a generic repository without IQueryable, but you might be able to use delegates/lambda functions to incorporate it.
Edit2: And just in case I didn't answer your question correctly, if you are asking if you are supposed to call your repository's Get() method from the service then yes, that is the correct DDD design as well. The reason is that the service layer is supposed to handle all your business logic, so it decides exactly how and what data to retrieve (for example, do you want it in alphabetical order, unordered, etc...). It also means that it can perform validation after loading if needed or validation before deleting and/or saving.
This means that the service layer doesn't care exactly how that data is stored and retrieved, it only decides what data is stored and retrieved. It then calls on the repository to handle the request correctly and retrieve/store the data in the way the service layer tells it to. Thus you have correct separation of concerns.

MVC Custom Model - Where is a simple example?

I need to make a web application and I want to use MVC. However, my Model can't be one of the standard Models -- the data is not stored in a database but instead in an external application accessible only via a API. Since this is the first MVC application I've implemented I'm relying on examples to understand how to go about it. I can't find any examples of a non-DB based Model. An example of a custom Model would be fine too. Can anyone point me to such a beast? Maybe MVC is just to new and none exist.
It seems like I might be able to get away with the DataSet Model, however I've not seen any examples of how to use this object. I expect an example of DataSet could help me also. (Maybe it is the same thing?)
Please note: I've seen countless examples of custom bindings. This is NOT what I want. I need an example of a custom Model which is not tied to a specific database/table.
UPDATE
I found a good example from MS located here:
http://msdn.microsoft.com/en-us/library/dd405231.aspx
While this is the "answer" to my question, I don't really like it because it ties me to MS's view of the world. #Aaronaught, #jeroenh, and #tvanfosson give much better answers from a meta perspective of moving my understanding (and yours?) forward with respect to using MVC.
I'm giving the check to #Aaronaught because he actually has example code (which I asked for.) Thanks all and feel free to add even better answers if you have one.
In most cases it shouldn't matter what the backing source is for the actual application data; the model should be exactly the same. In fact, one of the main reasons for using something like a repository is so that you can easily change the underlying storage.
For example, I have an MVC app that uses a lot of web services - rarely does it have access to a local database, except for simple things like authentication and user profiles. A typical model class might look like this:
[DataContract(Namespace = "http://services.acme.com")]
public class Customer
{
[DataMember(Name = "CustomerID")]
public Guid ID { get; set; }
[DataMember(Name = "CustomerName")]
public string Name { get; set; }
}
Then I will have a repository interface that looks like this:
public interface ICustomerRepository
{
Customer GetCustomerByID(Guid id);
IList<Customer> List();
}
The "API" is all encapsulated within the concrete repository:
public class AcmeWSCustomerRepository : ICustomerRepository, IDisposable
{
private Acme.Services.CrmServiceSoapClient client;
public AcmeWSCustomerRepository()
: this(new Acme.Services.CrmServiceSoapClient())
public AcmeWSCustomerRepository(Acme.Services.CrmServiceSoapClient client)
{
if (client == null)
throw new ArgumentNullException("client");
this.client = client;
}
public void Dispose()
{
client.SafeClose(); // Extension method to close WCF proxies
}
public Customer GetCustomerByID(Guid id)
{
return client.GetCustomerByID(id);
}
public IList<Customer> List()
{
return client.GetAllCustomers();
}
}
Then I'll also probably have a local testing repository with just a few customers that reads from something like an XML file:
public class LocalCustomerRepository : ICustomerRepository, IDisposable
{
private XDocument doc;
public LocalCustomerRepository(string fileName)
{
doc = XDocument.Load(fileName);
}
public void Dispose()
{
}
public Customer GetCustomerByID(Guid id)
{
return
(from c in doc.Descendants("Customer")
select new Customer(c.Element("ID").Value, c.Element("Name").Value))
.FirstOrDefault();
}
// etc.
}
The point I'm trying to make here is, well, this isn't tied to any particular database. One possible source in this case is a WCF service; another is a file on disk. Neither one necessarily has a compatible "model". In this case I've assumed that the WCF service exposes a model that I can map to directly with DataContract attributes, but the Linq-to-XML version is pure API; there is no model, it's all custom mapping.
A really good domain model should actually be completely independent of the true data source. I'm always a bit skeptical when people tell me that a Linq to SQL or Entity Framework model is good enough to use throughout the entire application/site. Very often these simply don't match the "human" model and simply creating a bunch of ViewModel classes isn't necessarily the answer.
In a sense, it's actually better if you're not handed an existing relational model. It forces you to really think about the best domain model for your application, and not necessarily the easiest one to map to some database. So if you don't already have a model from a database - build one! Just use POCO classes and decorate with attributes if necessary, then create repositories or services that map this domain model to/from the API.
I think what you are looking for is really a non-DB service layer. Models, typically, are relatively simple containers for data, though they may also contain business logic. It really sounds like what you have is a service to communicate with and need a layer to mediate between the service and your application, producing the appropriate model classes from the data returned by the service.
This tutorial may be helpful, but you'd need to replace the repository with your class that interacts with the service (instead of the DB).
There is no fixed prescription of what a "Model" in MVC should be, just that it should contain the data that needs to be shown on screen, and probably also manipulated.
In a well-designed MVC application, data access is abstracted away somehow anyway, typically using some form of the Repository pattern: you define an abstraction layer (say, an IRepository interface) that defines the contract needed to get and persist data. The actual implementation will usually call a database, but in your case should call your 'service API'.
Here is an example of an MVC application that calls out to a WCF service.

Resources