I have a question concerning an issue that has already been disputed many times in stackoverflow (I apologize for this) but no general answer has ever been given because of the subjectivity of the topic from one case to another: can we add business logic to the repository layer according to the repository pattern? I have an MVC 3 application with ViewModels (that means I don't use the ViewData at all). The model is an LinqtoSQL EF of course connected to a database. Currently I am accessing the entities directly from the controllers which contain all the business logic and I wrap the data needed for the Views in specific ViewModels. Now I am starting to refactor and I realized that the best way to avoid code duplication, besides optimizing the ViewModels, is to delegate all the queries to a repository, which communicates with the EF, and create tailored methods to be used by the controller. Now, taking into account that I would like the repository to return actual objects and not expressions, I was thinking about delegating small pieces of business logic to the repository in order to make my code clearer. However for the sake of loose coupling, I would like to have your opinion. In the code shown below (which currently resides in the controller) all the variabl开发者_Go百科es except lprojectionPercactualValue are taken from the database. Therefore I wanted to move this piece of code to the repository and call a method with signature:
public string getColor (int ItemId, float lprojectionPercactualValue);
The method needs the ItemId in order to retrieve the values specific for that Item. What do you think about this design decision? Is it better to leave the code in the controller, move to another method still in the controller (create a method or even a class dedicated) or move it to the repository as explained?
if (litem.Ascending == true)
{
if (lprojectionPercactualValue < lminThreshold)
{
lcolor = "RED";
}
else if (lprojectionPercactualValue > lminThreshold && lprojectionPercactualValue < lmedThreshold)
{
lcolor = "YELLOW";
}
else //(percValue >= item.Max_Threshold)
{
lcolor = "GREEN";
}
}
else
{
if (lprojectionPercactualValue > lminThreshold)
{
lcolor = "RED";
}
else if (lprojectionPercactualValue < lminThreshold && lprojectionPercactualValue > lmedThreshold)
{
lcolor = "YELLOW";
}
else //(percValue <= item.Max_Threshold)
{
lcolor = "GREEN";
}
}
It is not recommended.
How does Repository now about the lminThreshold
? What if this value itself needs to come from a lookup table or a config file?
Move it to business layer - and if you do not have one, to the controller.
Wrap your EF logic inside a DAL layer that you proxy via a Repository class. This is raw data and since you require additional crunching on it, it is recommanded to have a service layer that uses it and applies your custom business rules over it. The Repository here is meant to discourage any DB code duplication.
At this point, you only check if the lprojectionPercactualValue goes over some treshold, but what if, at some point, you will need to compute that treshold in some fancy manner or you decide to perform some sort of validation or some other thing like that. These are all domain specific decisions and they should reside in a layer of their own.
IMHO, you'd better to add a business layer between controller and repository, and put your getColor code above into the business layer (or even break it into several methods if needed), what if you need it in other controllers, what if it is no longer a simple if/else, what if you have to get the thresholds values from a Web service tomorrow, do you want to have make all those changes in your controller or repository code?
精彩评论