I've got an ASP.NET MVC application, and I'm using the repository pattern, with service-specific repositories. I'm finding my setup is starting to feel very repetitive.
My layers look like this: UserController > UserService > UserRepository (the repository then uses entity framework)
The controller accepts the service in the constructor for testability:
public UserController(IUserService userService)
The service accepts the repository:
public UserService(IUserRepository)
The user might be able to update their business information, change their name, email, delete a contact address, etc.
So I end up with things like this in the service:
public class UserService {
User CreateUser(....);
User GetUserById(int id);
void UpdateUser(User user);
void DeleteUser(User user);
Business CreateBusiness(...);
Business GetBusinessById(int businessId);
void UpdateBusiness(Business business);
void DeleteBusiness(Business business);
IEnumerable<Business> GetBusinessesByUserId();
IEnumerable<BusinessType> GetBusinessTypes();
...
...
...
Each of these functions call functions like this in the repository layer:
public class UserRepository {
User CreateUser(....);
User GetUserById(int id);
void UpdateUser(User user);
void DeleteUser(User user);
Business CreateBusiness(...);
Business GetBusinessById(int businessId);
void UpdateBusiness(Business business);
void DeleteBusiness(Business business);
IEnumerable<Business> GetBusinessesByUserId();
IEnumerable<BusinessType> GetBusinessTypes();
...
...
...
Any time I need to do a CRUD/data access operation of any sort, I find myself doing the following:
This is getting cumbersome, especially when there are multiple entities related to a particular service/repository. Multiply by multiple repositories and services throughout the application...
For background, I moved away from generic repositories to avoid the complexity of injecting multiple repositories left and right into service and/or controller constructors (or individual service functions).
It seems I am violating DRY, and constantly repeating myself. Is this as close as I can get, or is there a more efficient way to do this?? Thanks.
First. Service layer shouldn't repeat repository functions. Instead of UserService.UpdateUser
function, there should be UserService.UpdateBasicData
, UserService.UpdatePassword
taking subset of User
object fields. You generally shouldn't expose ORM layer objects in service. User
object surely has many properties and UpdateUser
function shouldn't change them, so it shouldn't mistake service consumer, that it may change them.
Second. You can still use generic repositories and make repository aggregation for injection. Example:
public class UserRelatedRepositories : IUserRelatedRepositories {
IRepository<User> User { get; set; }
IRepository<Business> Business { get; set; }
}
and then use
UserRelatedRepositories.User.Create()