I've been playing around with asp.net MVC3 a bit and have been struggling to decide where to place my business logic. I've settled on using a service layer for now:
public class AnimalsService : IAnimalsService
{
private readonly IAnimalsRepository _animalsRepository;
public AnimalsService(IAnimalsRepository animalsRepository)
{
_animalsRepository = animalsRepository;
}
public IQueryable<Animal> GetFiveLeggedAnimals()
{
...
}
}
The controller would look something like this:
public class AnimalsController : Controller
{
private readonly IAnimalsService _animalsService;
public AnimalsController(IAnimalsService animalsService)
{
_animalsService = animalsService;
}
public ViewResult ListFiveLeggedAnimals()
{
var animals = _animalsService.GetFiveLeggedAnimals();
return View(animals);
}
}
I have basic CRUD logic in the repository (All, Find, UpdateOrInsert, Delete). If I want to use these CRUD methods in my controller:
1) Do I have to create wrapper methods in the service for these respository calls?
2) Would it not make more sense for me to just include the GetFiveLeggedAnimals method and other business logic in the repository?
3) Could I implement the IAnimalsRepository interface in the AnimalsService and then call the base methods (I realise this is possible but I assume its bad practice)?
1) Do I have to create wrapper methods in the service for these respository calls?
Mostly, yes. Typically, you want to offer CRUD for your domain models in the service layer. This way, the controller does not need to work with the repository directly (in fact, it never should). You can add more more sophisticated logic later without having to change external code. For example, consider you wanted to implement a newsfeed. Now every time a five-legged animal is inserted, you want to create a news item and push it to five-legged-animal-fans. Another common example is email notifications.
2) Would it not make more sense for me to just include the GetFiveLeggedAnimals method and other business logic in the repository?
Business logic should be in the Service Layer or in the Domain Model objects themselves, and only there. In fact (see 3), I wouldn't specifically offer an IAnimalRepository at all, if possible.
For instance, in a NoSQL-Environment, the database driver pretty much is a repository. On the other hand, when using a complex ORM mapping and stored procedures (where part of the biz logic is in the DB), you don't really have a choice but offer explicit interfaces that know the stored procedures.
I'd go for a IRepository<T> and use the Query Object pattern, if possible. I think LINQ can also be considered a Query Object / Repository based pattern.
3) Could I implement the IAnimalsRepository interface in the AnimalsService and then call the base methods (I realise this is possible but I assume its bad practice)?
To call the base methods, you'd have to inherit from a concrete implementation, e.g. from ConcreteAnimalsRepository.
Also, if your service implements the IAnimalsRepository interface directly or indirectly, it makes the (unfiltered) CRUD operations available to everyone.
My take: Don't inherit, aggregate. A service layer has a repository, but it isn't a repository itself: The service layer handles all the additional application logic (permissions, notifications) and the repository is a very thin wrapper around the db layer.
As an extreme example, what if deleting something directly was forbidden, and only the service would be allowed to make use of it when inserting a newer revision of sth.? This can be easily built when aggregating.
Repository by definition should be a generic collection-like class that abstracts DB interactions. It would contain typical methods for persistence like Get(object id), Add(T), Remove(T) and possibly implement IQueryable<T>.
The service would look like the following code.
public class AnimalsService : IAnimalsService
{
private readonly IRepository<Animal> _repository;
public AnimalsService(IRepository<Animal> repository)
{
_repository = repository;
}
public IEnumerable<Animal> GetFiveLeggedAnimals()
{
// animal specific business logic
}
}
I think is not good to use simple CRUD operation in the Controller and have a wrapper in the Service class, you should keep all business logic in the service layer, not in controller
for example you want to create a new Animal
in the controller you will have method
look at the example
// not good design
public ActionResult Create(AnimalInput input)
{
Animal animal = new Animal { Name = input.Name}; // set the other propreties
// if you have a CRUD operations in service class you will call
animalService.UpdateOrInsert(animal);
}
// better disign
public ActionResult Create(AnimalInput input)
{
animalService.Create(input.Name);
}
in the service class implementation you should have
follow
public void Create(string name)
{
Animal animal = new Animal { Name = input.Name};
animalRepository.UpdateOrInsert(animal);
}
for the methods like GetAll or GetFiveLeggedAnimals(); you can have wrapper in the service classes I think it's ok . And I want to give you adives allways when you write some code in controller or in Service class keep in mind how you will test this code
and don't forget about SOLID
Related
I am making a web api and have created several classes, the class controller and the service as well as the dto and the model.
In the controller I have the methods for post and get and the business logic is in the service
My question is how can I make the queries from the model class and map the queries to the dto
Service Layer:
public class GermanyService : IGermanyService
{
public Task<IEnumerable<GermanyDto>> All()
{
throw new NotImplementedException();
}
public Task Create(GermanyDto germany)
{
throw new NotImplementedException();
}
}
Controller:
public class GermanyController
{
private readonly IGermanyService _germanyService;
public GermanyController(IGermanyService service)
{
_germanyService = service;
}
[HttpGet]
public async Task<IEnumerable<GermanyDto>> Get(int id)
{
return await _germanyService.All();
}
[HttpPost]
public async Task Post([FromBody]GermanyDto dto)
{
await _germanyService.Create(dto);
}
Okay :)
Use an interface implementation ->
seggregate your business logic's interfaces, so you have many of them, split into their single responsibilities and then join them in one:
Example
public interface IStreetName {
string StreetName{get;set;}
}
public interface IPostCode {
string PostCode {get;set;}
}
... other implementations for an Address DTO f.x.
then
public interface IAddress : IPostCode, IStreetName, ...
{
//should be empty
}
now you can Implement Iaddress on your DAL object, and not need an actual DTO -> because you ONLY reference the interface in your business logic.
etc.
Obviously, you would have to rename the intefaces for the properties on your "GermanyDTO", which I don't know what looks like.
EDIT:
Using mappers like "auto-mappers" or the like is usually a sign of 2 things.
1: You don't understand how to write effective mapping yourself.
2: Using a framework to accomplish something, doesn't absolve you from testing. And frameworks are notoriously difficult to test.
(Because, following proper procedure, you would have to test the interface between your code and the framework, and by extension the code between framework and 3rd part component, failing to do so, will setup you up for risks, between what you THINK the framwork does, and what it ACTUALLY does)
So Yes, using something like "Automapper" is at best a supression of a symptom rather than a cure.
Because the root cause is failing to understand how interfaces solve mappings.
And using a tool, to do something you can do cleaner yourself, and improve the structure of your entire system as a result? Is a no-brainer.
Just notice your own statement:
"Do you think it is effective? Automapper solves some of my issues"
You are seriously going to implement a direct dependency in your system, because of a framework?
You are admitting to writing bad code, because a framework can take away ... what? A little bit of boiler plate?
In the code I am working on I have a structure where some portions of the code depend on the current software session. Software session contains multiple helper objects which are dependency injected by composition.
One example is IRepository injected to it, which contains access to the data repository. And the IRepository contains a DatabaseContext which writes to a database, via IDbContext again which is injected.
SoftwareSession is the only injected common infrastructure for accessing all the way to the database, acting as a gateway. This means when I want to write an object to database, for instance WriteCar I will have to implement 3 interfaces, 2 functions delegating to composed objects and 1 function with implementation. It is clarified in the code fragment below. The WriteCar signatures are defined the same in 3 interfaces (IRepository, ISoftwareSession, IDbContext), 2 places where it is not implemented (Repository, SoftwareSession) which simply calls composited objects related functions and 1 place of actual implementation (IDbContext)
This means when I want to refactor, move code, add functionality or change function signatures I will always have to change 6 places for one function.
I think this provides the best environment for improving testability and it follows best practices where software session wraps access to repository and repository wraps access to data contexts - yet I still am questioning if we can have some better way of writing it once, or do I have a misunderstanding of some concept in the code below?
What is the architecturally more maintainable way of implementing this? Maybe even using some clever way of lambdas or delegates to reduce the amount of code written for each new functionality? Or even some libraries (like automapper simplifies DTOs) or tools to ease generation of this code from some kind of templating mechanism using Visual Studio, Resharper, etc?
Please let me know if I am having some confusion of concepts here. I know some my colleagues have similar views, in which case it may be helpful to clarify misunderstandings of others as well.
public class SoftwareSession : ISoftwareSession
{
...
IRepository repository;
public void WriteCar(Car car){
repository.WriteCar(car);
}
...
}
public interface ISoftwareSession{
...
void WriteCar(Car car);
...
}
public class Repository : IRepository{
...
IDbContext context;
public void WriteCar(Car car){
context.WriteCar(car);
}
...
}
public interface IRepository{
...
void WriteCar(Car car);
...
}
public class MyDbContext : IDbContext{
...
public void WriteCar(Car car){
//The Actual Implementation here.
...
}
...
}
public interface IDbContext{
...
void WriteCar(Car car);
...
}
For one thing, your IDbContext and IRepository are the same. You would probably like to remove IDbContext, or at least to remove methods declared in IRepository from it.
Then, both MyDbContext and Repository would implement IRepository and Repository class would just be a wrapper around MyDbContext.
Then, if Repository is only forwarding calls to MyDbContext, then you probably don't need that class either.
Furthermore, I don't see that you are doing anything in the SoftwareSession apart from forwarding the call to the contained repository. Do you really need SoftwareSession, or would it make sense to pass IRepository directly to whoever is calling the session object?
Bottom line is that this implementation is swarming with duplication and forwarding. Remove that, and your entire model would become simple.
Without seeing your composition root, I'm not entirely sure how your implementation works, but I'd suggest looking into using an Inversion of Control (IoC) container. Since your ISoftwareSession implementation only depends on an IRepository instance, you only need to inject that in the class' constructor. The same goes for your IRepository implementation: you only need to inject your IDbContext into the constructor.
With the IoC container, you "register", i.e. wire up your interfaces to your implementation at application startup (in the composition root), and the container takes care of creating the required instances when you resolve the dependencies. Then all you have to do is get the instance of SoftwareSession from the container, and away you go.
So, you could change your SoftwareSession implementation like this:
public class SoftwareSession : ISoftwareSession
{
IRepository repository;
public SoftwareSession(IRepository repository)
{
this.repository = repository;
}
public void WriteCar(Car car)
{
repository.WriteCar(car);
}
}
And your Repository implementation like this:
public class Repository : IRepository
{
IDbContext context;
public Repository(IDbContext dbContext)
{
context = dbContext;
}
public void WriteCar(Car car)
{
context.WriteCar(car);
}
}
Then here is your composition root:
var ioc = new MyIocContainer();
// register your interfaces and their associated implementation types with the IoC container
ioc.Register<ISoftwareSession, SoftwareSession>();
ioc.Register<IRepository, Repository>();
ioc.Register<IDbContext, MyDbContext>();
// resolve the IoC container
ioc.Resolve();
// get your `ISoftwareSession` instance
var session = ioc.GetConcrete<ISoftwareSession>();
var newCar = new Car();
session.WriteCar(newCar);
I would like that in my MVC layer there will be no Repositories at all.
I've generic EFRepository, IRepository and PASContext (which inherits from DbContext) in my DAL project layer .
I've installed Simple Injector with quick start under my MVC project and thats allows me to get in the constructor of each controller the repository i want .
But in my solution i have also BLL project and i want MVC layer to talk only with the BLL layer, as this is the project architecture and in the future i would like to add logic in the classes within the BLL layer .
Also i don't want to create a context in my BLL layer, but the Repository has no constructor which takes 0 arguments, this is my ProductBLL class :
public class BLLProducts
{
IRepository<Product> ProductRepository;
public BLLProducts(EFRepository<Product> Repository)
{
ProductRepository = Repository;
}
public ICollection<Product> getAll()
{
return ProductRepository.All().ToList();
}
}
How can i initiate the BLLProduct class from a controller or from a unitTest without creating a repository/context ? so i can keep my abstraction here.
I know i need to use somehow the Simple injector here, i just dont know how .
From perspective of the controller, it's just a matter of injecting the BLLProducts into it, like this:
// constructor
public HomeController(BLLProducts products) {
this.products = products;
}
From a unit testing perspective, letting the controllers depend on concrete classes is suboptimal (it violates the Dependency Inversion Principle). This is sub optimal, since you now need to create a BLLProducts instance and instantiate it with a DbContext, but this DbContext is specific to Entity Framework, which depends on a database. This makes testing harder and slower. You want your unit tests to run without a database.
So the solution to this is to hide this BLLProducts class behind an abstraction. A simple way to do this is extract an interface out of this class:
public interface IBLLProducts {
ICollection<Product> getAll();
}
This makes unit testing the controllers much easier. The only thing you have to do is let it depend on this new interface:
public HomeController(IBLLProducts products) {
this.products = products;
}
You will need to register this IBLLProducts interface in Simple Injector:
container.Register<IBBLProducts, BLLProducts>();
This whole model still has some downsides to it. For instance, although Simple Injector can create and dispose a DbContext for you, where do you call SubmitChanges? Doing this when the web requests ends is a pretty bad idea. The only convenient solution I found for this is to move to a more SOLID architecture. For instance, take a look at this question.
I'm wondering if there is a better way to approach this problem. The objective is to reuse code.
Let’s say that I have a Linq-To-SQL datacontext and I've written a "repository style" class that wraps up a lot of the methods I need and exposes IQueryables. (so far, no problem).
Now, I'm building a service layer to sit on top of this repository, many of the service methods will be 1<->1 with repository methods, but some will not. I think a code sample will illustrate this better than words.
public class ServiceLayer
{
MyClassDataContext context;
IMyRepository rpo;
public ServiceLayer(MyClassDataContext ctx)
{
context = ctx;
rpo = new MyRepository(context);
}
private IQueryable<MyClass> ReadAllMyClass()
{
// pretend there is some complex business logic here
// and maybe some filtering of the current users access to "all"
// that I don't want to repeat in all of the public methods that access
// MyClass objects.
return rpo.ReadAllMyClass();
}
public IEnumerable<MyClass> GetAllMyClass()
{
// call private IQueryable so we can do attional "in-database" processing
return this.ReadAllMyClass();
}
public IEnumerable<MyClass> GetActiveMyClass()
{
// call private IQueryable so we can do attional "in-database" processing
// in this case a .Where() clause
return this.ReadAllMyClass().Where(mc => mc.IsActive.Equals(true));
}
#region "Something my class MAY need to do in the future"
private IQueryable<MyOtherTable> ReadAllMyOtherTable()
{
// there could be additional constrains which define
// "all" for the current user
return context.MyOtherTable;
}
public IEnumerable<MyOtherTable> GetAllMyOtherTable()
{
return this.ReadAllMyOtherTable();
}
public IEnumerable<MyOtherTable> GetInactiveOtherTable()
{
return this.ReadAllMyOtherTable.Where(ot => ot.IsActive.Equals(false));
}
#endregion
}
This particular case is not the best illustration, since I could just call the repository directly in the GetActiveMyClass method, but let’s presume that my private IQueryable does some extra processing and business logic that I don't want to replicate in both of my public methods.
Is that a bad way to attack an issue like this? I don't see it being so complex that it really warrants building a third class to sit between the repository and the service class, but I'd like to get your thoughts.
For the sake of argument, lets presume two additional things.
This service is going to be exposed through WCF and that each of these public IEnumerable methods will be calling a .Select(m => m.ToViewModel()) on each returned collection which will convert it to a POCO for serialization.
The service will eventually need to expose some context.SomeOtherTable which wont be wrapped into the repository.
I think it's a good model since you can create basic IQueryable private functions that can be used by the functions you are exposing publicly. This way your public methods do not need to recreate a lot of the common functionality your IQueryable methods perform and they can be extended as needed and deferring the execution while still hiding that functionality publicly.
An example like how to get X out of some table which may take a lot of logic that you don't need in it's raw form. You then have that as a private method, as you do in your example, and then the public method adds the finalizing criteria or queries to generate a useable set of data which could differ from function to function. Why keep reinventing the wheel over and over... just create the basic design (which you IQueryable does) and drop on the tread pattern that is required as needed (your public IEnumerable does) :)
+1 for a good design IMO.
Using LINQ TO SQL as the underpinning of a Repository-based solution. My implementation is as follows:
IRepository
FindAll
FindByID
Insert
Update
Delete
Then I have extension methods that are used to query the results as such:
WhereSomethingEqualsTrue() ...
My question is as follows:
My Users repository has N roles. Do I create a Roles repository to manage Roles? I worry I'll end up creating dozens of Repositories (1 per table almost except for Join tables) if I go this route. Is a Repository per Table common?
If you are building your Repository to be specific to one Entity (table), such that each Entity has the list of methods in your IRepository interface that you listed above, then what you are really doing is an implementation of the Active Record pattern.
You should definitely not have one Repository per table. You need to identify the Aggregates in your domain model, and the operations that you want to perform on them. Users and Roles are usually tightly related, and generally your application would be performing operations with them in tandem - this calls for a single repository, centered around the User and it's set of closely related entities.
I'm guessing from your post that you've seen this example. The problem with this example is that all the repositories are sharing the same CRUD functionality at the base level, but he doesn't go beyond this and implement any of the domain functions. All the repositories in that example look the same - but in reality, real repositories don't all look the same (although they should still be interfaced), there will be specific domain operations associated with each one.
Your repository domain operations should look more like:
userRepository.FindRolesByUserId(int userID)
userRepository.AddUserToRole(int userID)
userRepository.FindAllUsers()
userRepository.FindAllRoles()
userRepository.GetUserSettings(int userID)
etc...
These are specific operations that your application wants to perform on the underlying data, and the Repository should provide that. Think of it as the Repository represents the set of atomic operations that you would perform on the domain. If you choose to share some functionality through a generic repository, and extend specific repositories with extension methods, that's one approach that may work just fine for your app.
A good rule of thumb is that it should be rare for your application to need to instantiate multiple repositories to complete an operation. The need does arise, but if every event handler in your app is juggling six repositories just to take the user's input and correctly instantiate the entities that the input represents, then you probably have design problems.
Is a Repository per Table common?
No, but you can still have several repositiories. You should build a repository around an aggregate.
Also, you might be able to abstract some functionality from all the repositories... and, since you are using Linq-to-Sql, you probably can...
You can implement a base repository which in a generic way implements all this common functionality.
The following example serves only to prove this point. It probably needs a lot of improvement...
interface IRepository<T> : IDisposable where T : class
{
IEnumerable<T> FindAll(Func<T, bool> predicate);
T FindByID(Func<T, bool> predicate);
void Insert(T e);
void Update(T e);
void Delete(T e);
}
class MyRepository<T> : IRepository<T> where T : class
{
public DataContext Context { get; set; }
public MyRepository(DataContext context)
{
Context = Context;
}
public IEnumerable<T> FindAll(Func<T,bool> predicate)
{
return Context.GetTable<T>().Where(predicate);
}
public T FindByID(Func<T,bool> predicate)
{
return Context.GetTable<T>().SingleOrDefault(predicate);
}
public void Insert(T e)
{
Context.GetTable<T>().InsertOnSubmit(e);
}
public void Update(T e)
{
throw new NotImplementedException();
}
public void Delete(T e)
{
Context.GetTable<T>().DeleteOnSubmit(e);
}
public void Dispose()
{
Context.Dispose();
}
}
To me the repository pattern is about putting a thin wrapper around your data access methodology. LINQ to SQL in your case, but NHibernate, hand-rolled in others. What I've found myself doing is create a repository-per-table for that is extremely simple (like bruno lists and you already have). That is responsible for finding things and doing CRUD operations.
But then I have a service level that deals more with aggregate roots, as Johannes mentions. I would have a UserService with a method like GetExistingUser(int id). This would internally call the UserRepository.GetById() method to retrieve the user. If your business process requires the user class returned by GetExistingUser() to pretty much always need the User.IsInRoles() property to be filled, then simply have the UserService depend upon both the UserRepository and RoleRepository. In pseudo code it could look something like this:
public class UserService
{
public UserService(IUserRepository userRep, IRoleRepository roleRep) {...}
public User GetById(int id)
{
User user = _userService.GetById(id);
user.Roles = _roleService.FindByUser(id);
return user;
}
The userRep and roleRep would be constructed with your LINQ to SQL bits something like this:
public class UserRep : IUserRepository
{
public UserRep(string connectionStringName)
{
// user the conn when building your datacontext
}
public User GetById(int id)
{
var context = new DataContext(_conString);
// obviously typing this freeform but you get the idea...
var user = // linq stuff
return user;
}
public IQueryable<User> FindAll()
{
var context = // ... same pattern, delayed execution
}
}
Personally I would make the repository classes internally scoped and have the UserService and other XXXXXService classes public so keep your consumers of the service API honest. So again I see repositories as more closely linked to the act of talking to a datastore, but your service layer being more closely aligned to the needs of your business process.
I've often found myself really overthinking the flexibility of Linq to Objects and all that stuff and using IQuerable et al instead of just building service methods that spit out what I actually need. User LINQ where appropriate but don't try to make the respository do everything.
public IList<User> ActiveUsersInRole(Role role)
{
var users = _userRep.FindAll(); // IQueryable<User>() - delayed execution;
var activeUsersInRole = from users u where u.IsActive = true && u.Role.Contains(role);
// I can't remember any linq and i'm type pseudocode, but
// again the point is that the service is presenting a simple
// interface and delegating responsibility to
// the repository with it's simple methods.
return activeUsersInRole;
}
So, that was a bit rambling. Not sure if I really helped any, but my advise is to avoid getting too fancy with extension methods, and just add another layer to keep each of the moving parts pretty simple. Works for me.
If we write our repository layer as detailed as Womp suggests, what do we put in our service layer. Do we have to repeat same method calls, which would mostly consists of calls to corresponding repository method, for use in our controllers or codebehinds? This assumes that you have a service layer, where you write your validation, caching, workflow, authentication/authorization code, right? Or am I way off base?