Calling a service from another service

Apr 8, 2014 at 8:31 PM
Hi,
In real life there are always situations where you need to call methods that exists on a specific service from another service, following the concept of separation of concerns.

Imagine this situation:
I have a service created with all typical methods for CRUD operations for the entity User. Every time that any attribute of User changes, I need to make sure that the action is recorded in a separate entity called Audit, with the information of the user that changes these attributes and the current date.

I would like to know what your point of view is on where to implement this code.
My assumption is that the implementation of the Update method for the User service should contain a code to add a new record on the Audit entity through its service or repository with the information of the transaction.

I did not see how to implement such a scenario with the existing code, all options that I can think of involves changing the framework.

Thank you in advance.
Apr 9, 2014 at 12:44 PM
Hi darioek

You describe exactly the scenario I run into yesterday night. I wonder what implementation is suggested.

In my opinion it should be allowed to instantiate the required service from the current parent service and pass the new repository as parameter to the required service. The new repository can be retrieved through the parent's existing service repository (e.g repository.GetRepository<Audit>()) which allows you to interact in the same UOW as the parent is currently working.

Best regards
Coordinator
Apr 9, 2014 at 5:56 PM
Several teams have implemented logging with the Framework, most have implemented logging into the DataContext.cs in the SaveChanges and SaveChangesAsync methods.
Apr 9, 2014 at 6:55 PM
Implementing logging in such a deep layer may be useful if you want to log every data-change without differentiating by type. How would you implement specific data-change logging with user assignment / management? We do not have any access to the entities / POCO's from inside the framework in case we need to add a new audit or user entry to the database. Due to the generic implementation of the framework I wonder how teams implement logging functionality. In my opinion the DataContext class is not meant to be filled with business logic.

I still believe this functionality has to be available from a service as originally described by darioek. This takes us back to the original question....Can we call other services from the current service? What do you think for best-practice? Maybe I am totally wrong, please let me know ;-)

Thanks & best regards
Apr 9, 2014 at 7:04 PM
Thank you lelong37 for your feedback.

I'm not trying to implement a logging mechanism, instead the purpose is to be able to consume other services from any given service. There are plenty of situation where you need to do this.

From a design perspective, services should be able to encapsulate business related rules and they may need to interact with other repositories to be able to perform a business action. The typical example is placing an order and making sure that you have the products in stock before saving the order. In this case, OrderService should be able to call the Product service/repository to ensure there are available products.

I believe services should be able to access the UnitOfWork so they can interact with other repositories.

Do you see any problems with this?

Thank you
Coordinator
Apr 9, 2014 at 7:09 PM
Hi Darioek, there is a similar (not exact) discussion around this topic: https://genericunitofworkandrepositories.codeplex.com/discussions/539784, have a quick glance and please let me know what thoughts are afterwards.
Marked as answer by lelong37 on 4/16/2014 at 10:43 AM
Apr 9, 2014 at 11:57 PM
Thanks!

This will work for me. The implementation should be something like this:
public override void Update(Order order)
        {
            var productSvc = new ProductService(_repository.GetRepository<Product>() as IRepositoryAsync<Product>);

            if (productSvc.ProductInStock(order.ProductId))
                _repository.Update(order);
            else
                throw new Exception("Product is not available");
        }
Thank you