0

I have an ASP.NET MVC3 in C# and Razor. The architecture of the application is divided in Data Access Layer (EF classes + Repository), Service Layer, Controller, ViewModels and View.

From my Service Layer ProductServices I call the method GetAllProducts exposed by my Repository ProductRepository , which has the following signature:

IQueryable<Products> GetAllProducts()

Therefore within ProductServices I call (productRepository is an instance of ProductRepository):

var products = productRepository.GetAllProducts(); 

that populates the variable products. Now I would like to access the name of the product ProductName from productServices. If I use this instruction:

var productNames = products.Select(m => m.ProductName).ToList();

I am creating coupling between ServiceLayer and the EF (bypassing the repository). That means I must add to ProductRepository a method with signature:

IQueryable<string> GetAllProductsName()

However, since I need other product information in my application, shall I create one method in productRepository for each field of the Product class? Is my reasoning correct? Thanks

CiccioMiami
  • 8,028
  • 32
  • 90
  • 151
  • Why would you need service layer if it is there to just proxy the requests? – Eranga Feb 20 '12 at 11:49
  • thanks for your answer. Of course I have also all the business logic and several methods in my service layer, that's why I need it – CiccioMiami Feb 20 '12 at 11:56
  • What makes you think this type of coupling is bad? – Eranga Feb 20 '12 at 11:59
  • Because I already know in advance that in one year the database is going to be replaced by another one. That means the name of the fields are most likely to be changed and I should also change them in my Repository and, in case of coupling, also in my Service Layer – CiccioMiami Feb 20 '12 at 12:36

2 Answers2

1

Theres two schools of thought around this,

  1. A repository explicitly defines the way you interact with the database and should be tightly controlled. Therefore methods on the repository should provide enumerated data
  2. The repository breaks the strong coupling to a specific datasource type but does not need to provide detailed and enumerated datasets.

Personally i subscribe to the second, heres why:

my feeling is that when you get overly explicit within the repository it turns into business logic rather than a decoupling mechanism. I don't really like this as it means that you become more tightly linked to the repository implementation.

I also think that in some cases the repository isnt the right place to enumerate the data, for example I believe paging and sorting is a UI concern, however for performance you want queries to only relate to the current page/sort. this means you either need to let the UI contribute to the query compilation or the repository needs to understand paging and sorting.

Having said that providing un-enumerated datasources does open you up for issues later down the track, and even if you do provide them its very important to enumerate the set as soon as possible.

If you're interested heres my take on the repositories: http://blog.staticvoid.co.nz/2011/10/staticvoid-repository-pattern-nuget.html , all the code is also on github

undefined
  • 33,537
  • 22
  • 129
  • 198
  • thanks for your answer. Therefore you suggest me not to create specific methods and access the field through the Service Layer, bypassing the repository? – CiccioMiami Feb 20 '12 at 12:01
  • My feeling is that by accessing the queriable directly you actually aren't bypassing the repository, you're kinda doing a run time extension. so yes i would be fine using a select after you get the set back from the repository. Its also important to note here that the select is actually a function of LINQ not of EF or your repository and it will quite happily work on an enumerated set as well. – undefined Feb 20 '12 at 12:05
  • and if I know in advance that the database (and consequently the EF) is going to be replaced? If I access the fields just from `productRepository` I have to change just that layer – CiccioMiami Feb 20 '12 at 12:38
  • yeah of course changing the layer shouldnt be a problem, the only gotcha around this is that if the new ORM you are use doesnt support compiling linq to SQL your repository method may perform a little slower as the query will pull back more stuff. – undefined Feb 20 '12 at 19:14
0

You have all information in your productServices because you load all information from your Repository with the method productRepository.GetAllProducts(). If you need more information from an other entity then you need to extend your productServices with a new Service.

However, since I need other product information in my application, shall I create one method in productRepository for each field of the Product class? Is my reasoning correct? Thanks

In this situation normally I create Extensions method's for the service and not in the repository. The Repository have normally a CRUD Setup and nothing more.

theforce
  • 1,505
  • 1
  • 11
  • 13
  • thanks, that means you access the fields directly in the Service Layer right? Of course I have other methods besides GetAllProducts I didn't list them here because they are out of question's scope – CiccioMiami Feb 20 '12 at 14:14
  • In this case yes. You never no, if you need this logic in an other application-or database-context(e.q WPF App or Mobile App). With your service architecture you can handle this situation in a good way. – theforce Feb 20 '12 at 17:21