locked
Responsibilities of Service Layer and Repository Layer RRS feed

  • Question

  • User-2028223751 posted

    I'm in the throes of my first real MVC project.  I started off the easy way, by chucking everything into the controllers.  Once I had a few done and was getting a feel for it, I started refactoring out a repository layer.  Now I've got a few more controllers up and running I'm going to refactor out a service layer.  Note also that I'm using the Entity Framework for the DAL.

    I'm looking for comments on two approaches to structuring the interface between the service and repository layers.  I'm trying to decide between two options:

    1. Having fewer methods exposed in the repository that each return an IQueryable, then have the service layer add some refinements to the queries before calling ToArray and returning an IEnumerable.

    2. Having more methods exposed in the repository that each call ToArray and return an IEnumerable.

    Option 1 means that it would be the right and responsibility of the service layer to call a single repository method and specify Where conditions, etc. itself, rather than calling several different repository methods.  I like that idea, but it also feels a bit like putting data access into the service layer.  It also means that, if I was to swap out the repository layer for something hand-crafted, I'd have to artifically create IQueryable results.  What say you?

    Wednesday, November 18, 2009 7:56 AM

Answers

  • User1911587250 posted

    example you talk about is about validating (and more related to BLL) but the problem was about Repository .

    I agree with you in dieting the v in MVC but arguing you in separating concerns .

    if refining that we make in service layer is more related to a view(just one) better way is to move the code to controller but if refining code is going to be used is more and more views better way is to move code to a service we can use again and again .

    this makes sense like normalizing and demoralizing  is DB.

    and I’m agree with the writer of the example you talk about to separating validation login from controller and moving it to a BLL layer or service or what you name it !

    hope this helps.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, November 18, 2009 12:23 PM
  • User1588608489 posted

    I am not a fan of having a service layer contain a bunch of logic.  I think of a "Service Layer" nothing more than a layer that is responsible for delegating to "other" manager classes, repository classes, etc.  IMO, a good service layer will allow you to easily mock its dependencies and behaviors.

    However, the repositories can get nasty if you have a bunch of queries...

    I would consider making your repositories fairly generic, but allow the consumers of the repositories inject options into the repositories.  The query options would be stored in a simple class that has utility methods.

    Here is some pseudo code....

    public Procedures GetProceduresByName(string name) {
        ValidateName(name);
        Procedures result = null;
        try {
            result = procedureRepository.GetProceduresByName(name, ProcedureOptions.IncludeWarnings());
        }
        catch (Exception ex) {
            policyHandler.HandleException(ex);
        }
    
        return result;
    }


    The service implementation chooses to use some procedure options when it calls into the repository. It does NOT have a bunch of logic...

    Here is another real world example, that is kind of complicated.  It is a soap based WCF service that delegates to a 3rd party shipping service to lookup some shipping details.  It validates the request, delegates to the 3rd party service, builds the response, logs to the event log, and returns the response.  If any errors occur during validation or downstream, they are handled by other code...

     [PrincipalPermission(SecurityAction.Demand, Role = UserRoles.Anonymous)]
     public GetShipmentInformationResponse GetShipmentInformation(GetShipmentInformationRequest request)
     {
        ValidateGetShipmentInformationRequest(request);
        GetShipmentInformationResponse response = new GetShipmentInformationResponse();
        try {
            switch (request.ShippingProvider) {
                case ShippingProvider.UPS:
                    response = GetUPSShipmentTracking(request.TrackingNumber);
                    break;
            }
            eventLogService.WriteEvent(
                new WriteEventRequest(
                    LogEntryBuilder.GetShipmentInformation(request.TrackingNumber, request.ShippingProvider)));
        }
        catch (Exception ex) {
            if (policyHandler.HandleException(ex, ServicePolicyName))
                throw;
        }
        return response;
    }


     

    Hope this helps you decide.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, November 19, 2009 2:59 AM

All replies

  • User-434868552 posted

    This tutorial may help you:

    Validating with a Service Layer View in VB or C#



    Regards,
    Gerry (Lowry)

    Wednesday, November 18, 2009 9:03 AM
  • User1911587250 posted

    so because we pass IQueryable i think i doesn't make sence to bother ourselves by a service layer .

    we can have some refining login in our controler because most of these refinments relted to what we want to show in the view and somehow related to controller and view more than repository .

    Wednesday, November 18, 2009 11:31 AM
  • User-434868552 posted

    Totally disagree with ali62b.  Example, from http://www.asp.net/learn/mvc/tutorial-38-cs.aspx:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create([Bind(Exclude = "Id")] Product productToCreate)
    {
    if (!_service.CreateProduct(productToCreate)) return View();
    return RedirectToAction("Index");
    }

    The Controller, if necessary, must be put on a code reduction diet!!!

    Think of ASP.NET MVC as          MvC.

    Model =. "the boss" =. black box of black boxes representing business rules and data access

    Controller =. "the messenger" and only the messenger

    View =. "the face" =. gifted in rendering, with zero awareness of what is being rendered

    Wednesday, November 18, 2009 11:45 AM
  • User1911587250 posted

    example you talk about is about validating (and more related to BLL) but the problem was about Repository .

    I agree with you in dieting the v in MVC but arguing you in separating concerns .

    if refining that we make in service layer is more related to a view(just one) better way is to move the code to controller but if refining code is going to be used is more and more views better way is to move code to a service we can use again and again .

    this makes sense like normalizing and demoralizing  is DB.

    and I’m agree with the writer of the example you talk about to separating validation login from controller and moving it to a BLL layer or service or what you name it !

    hope this helps.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, November 18, 2009 12:23 PM
  • User-2028223751 posted

    Thank you for your input guys.

    I have been through all the MVC tutorials on the ASP.NET site and am using that very one, and the Contact Manager example, as my guide.  They don't really cover what I'm talking about though because they only cover quite simple cases.  Let me give you a couple of examples.

    One of my entities is Procedure, representing a medical procedure.  In one view in the admin app, the user can hide a procedure entirely, for a specific medical facility or for a specific doctor at a specific facility.  That procedure will then not be displayed on the public site for those criteria.  In another view , the user can assign warnings to a procedure, so that extra information will appear on the public site.

    In both cases, the user needs to be able to search for procedures by partial name.  They can search for a procedure whose name contains, equals, starts with or ends with a substring.  When hiding procedures, I need to include facility and doctor information in the result of my query, while when adding warnings I need to include warning information.

    So, should how do you think I should structure the service/repository interface:

    1. Expose 8 methods in the repsotiory, including GetProceduresByNameContainsWithFacilitiesAndDoctors, GetProceduresByNameEqualsWithFacilitiesAndDoctors, GetProceduresByNameStartsWithWithWarnings and GetProceduresByNameEndsWithWithWarnings.

    2. Expose a single method in the repository named GetProceduresByName and add parameters to indicate how the name relates to the supplied substring and what to include in the result set.

    3. Expose a single method in the repository named GetProceduresByName and let the service layer extend the IQueryable it returs by adding Where and Include calls.

    Wednesday, November 18, 2009 6:01 PM
  • User1911587250 posted

    option 3 is the choise here is the proof :

    let we separate concerns into DAL and BLL and PLL(Program Login Layer) layers then choose the right option.

    Repository goes to DAL

    search specifications you mentioned goes to BLL (View Service Layer in your app)

    controller  coded goes to PLL

    so as you see

    Repository should't aware of Business specifications (these 5 methodes you mentioned)

    and also Controller haven't any reponsibility to implement Business specification of How search should executed

    so thes 5 five methods go to BLL (Your Service classes)

    hope this  helps .


    Thursday, November 19, 2009 2:14 AM
  • User1588608489 posted

    I am not a fan of having a service layer contain a bunch of logic.  I think of a "Service Layer" nothing more than a layer that is responsible for delegating to "other" manager classes, repository classes, etc.  IMO, a good service layer will allow you to easily mock its dependencies and behaviors.

    However, the repositories can get nasty if you have a bunch of queries...

    I would consider making your repositories fairly generic, but allow the consumers of the repositories inject options into the repositories.  The query options would be stored in a simple class that has utility methods.

    Here is some pseudo code....

    public Procedures GetProceduresByName(string name) {
        ValidateName(name);
        Procedures result = null;
        try {
            result = procedureRepository.GetProceduresByName(name, ProcedureOptions.IncludeWarnings());
        }
        catch (Exception ex) {
            policyHandler.HandleException(ex);
        }
    
        return result;
    }


    The service implementation chooses to use some procedure options when it calls into the repository. It does NOT have a bunch of logic...

    Here is another real world example, that is kind of complicated.  It is a soap based WCF service that delegates to a 3rd party shipping service to lookup some shipping details.  It validates the request, delegates to the 3rd party service, builds the response, logs to the event log, and returns the response.  If any errors occur during validation or downstream, they are handled by other code...

     [PrincipalPermission(SecurityAction.Demand, Role = UserRoles.Anonymous)]
     public GetShipmentInformationResponse GetShipmentInformation(GetShipmentInformationRequest request)
     {
        ValidateGetShipmentInformationRequest(request);
        GetShipmentInformationResponse response = new GetShipmentInformationResponse();
        try {
            switch (request.ShippingProvider) {
                case ShippingProvider.UPS:
                    response = GetUPSShipmentTracking(request.TrackingNumber);
                    break;
            }
            eventLogService.WriteEvent(
                new WriteEventRequest(
                    LogEntryBuilder.GetShipmentInformation(request.TrackingNumber, request.ShippingProvider)));
        }
        catch (Exception ex) {
            if (policyHandler.HandleException(ex, ServicePolicyName))
                throw;
        }
        return response;
    }


     

    Hope this helps you decide.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, November 19, 2009 2:59 AM