I'm trying to implement an N-tier architecture using repositories and service layer in asp.net mvc application.
A Service object can own multiple repositories to collect all data it needs using the same unit of work.
Controllers call only Service objects and don't know anything about repositories.
Repository example:
public class UsersRepository : IUsersRepository
{
public IEnumerable<User> GetUsers(UsersQuery query)
{
...
}
}
UsersQuery objects incapsulates several options for querying Users, e.g:
public class UsersQuery
{
public bool IncludeDeleted { get; set; }
public Expression<Func<User, object>> OrderBy { get; set; }
//Ans so on...
}
How should I for example pass dynamic OrderBy clause (and other options) to my repository? Of course, it is possible just to pass Query object through the service, but it seems to me not to be the true way, as producing overhead and violating the DRY principle.
Any suggestions? Thanks in advance.
Related
I am building a Web API using Dapper for .NET Core and trying to adhere to Clean Architecture principles. The API is consumed by an external Angular front-end.
I have repositories that use Dapper to retrieve data from the database, and this data then passes through a service to be mapped into a DTO for display to the user.
It is my understanding that an entity should be an exact representation of the database object, with no extra properties, and that I should use DTOs if I require some additional properties to show the user (or if I wish to obscure certain properties from the user too).
Suppose I have a DTO:
public class StudentDTO
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<Assignment> Assignments { get; set;}
}
and its corresponding Entity:
public class Student
{
public Guid Id { get; set; }
public string Name { get; set; }
}
With this model, should I want to get a student with all of their assignments, I'd need to have two repository calls, and do something like this in the service:
public StudentDTO GetById(Guid id)
{
var student = this.studentRepository.GetById(id);
var assignments = this.assignmentRepository.GetByStudentId(id);
return SomeMapperClass.Map(student, assignments);
}
But this seems inefficient and unnecessary. My question is, should I not just retrieve the Assignments when I get the student entity in the repository, using a JOIN? Or would this violate what an entity is supposed to be?
I apologise, I do realise this is a rather simple question, but I'd really like to know which method is the best approach, or if they both have their use cases
I think it would be more efficient, since map uses reflections, that is slower tens times
public StudentDTO GetById(Guid id)
{
var student = this.studentRepository.GetById(id);
student.Assignments = this.assignmentRepository.GetByStudentId(id);
return student;
}
but the common way is
return _context.Students.Include(i=>i.Assignments).FirstOrDefault(i=> i.Id==id);
This is why the generic repository is a bad idea in the most casses, since it is hard to guess what set of data you will need.
In my onion architecture I've my PresentationLayer who contains a class named LogRabbitMQFilters with differents properties to filter search.
I pass LogRabbitMQFilters in ApplicationLayer by mapper :
public RabbitMQController(IELKService iELKService, IMapper mapper)
{
_iELKService = iELKService;
_mapper = mapper;
}
public async Task<IActionResult> Index(int? id, LogRabbitMQFilters filters)
{
var filtersMapped = _mapper.Map<LogRabbitMQFilters>(filters);
var response = await _iELKService.GetLog(filtersMapped);
/*some code.....*/
}
In ApplicationLayer I map my logRabbitMQFilters to RabbitMQFilters which is declare in Persistance layer and I call my repository like this :
public ELKService(IELKRepository iELKRepository, IMapper mapper)
{
_iELKRepository = iELKRepository;
_mapper = mapper;
}
public async Task<LogResult> GetLog(LogRabbitMQFilters logRabbitMQFilters)
{
var filterMapped = _mapper.Map<RabbitMQFilters>(logRabbitMQFilters);
return await _iELKRepository.GetLogs(filterMapped);
}
It's best approch to do this ? Is there another way to pass my filters class to the repository ? I thought of specification pattern but I don't now if it's a good solution.
DDD and onion architecture share common principles (e.g. domain isolation), however they also draw some different aspects regarding development techniques. It should be pointed out that architectures and designs should serve our goals rather than be the goals themselves.
From your description it seems you have a CRUD-style system. I see no business rules, no domain concepts, no specifications. And that is, of course, not a bad thing.
Isolating domain from other layers (presentation, infrastructure) is beneficial in particular when sophisticated validations are to be applied and business rules are to be enforced within complex entity objects. In your case, however, you map plain object LogRabbitMQFilters (presentation layer) to "itself" (application layer) then to plain object RabbitMQFilters (infrastructure layer). Passing an object as is from presentation layer to application layer is OK in cases like yours (even from a DDD/onion perspective), however:
The second mapping should not exist, since infrastructure layer knows domain and therefore should receive your (presumably) domain entity LogRabbitMQFilters.
LogRabbitMQFilters is actually not a true domain entity since, as mentioned before, it does not apply any business rule.
Flatly mapping objects from one layer to another seems pointless.
I thought of specification pattern but I don't now if it's a good solution
Specification pattern is very useful when we want to pack expressions as business invariants, e.g. having a class named ShortMessage (business invariant) encapsulating an expression such as Message.Length < 42. But with your case I see no use for that, due to the CRUD nature of your application: you simply receive some user properties to function as operands in the context of an ORM object representing a database table, in order to do something like that:
myORMManager
.FetchAll<MyTableObject>()
.Filter(record =>
record.DateDebut == filter.DateDebut &&
record.DateFin == filter.DateFin &&
.
.
record.Message == filter.Message
.
.
.
);
Each of the predicates separated by 'and' operator can be considered as specification, however such specifications are just technical, as they do not convey any business invariant. The object filter can actually be a client request.
To conclude, it is acceptable to develop a single-layer application directly using client properties as operands for database filter expressions, as long as business invariants are out of picture (or at least with low complexity). If you would still like to have a DDD framework, i.e. having an application service (where you may apply simple validations such as DateFin > DateDebut) and a repository object together with the controller object, then I would recommend to have a single class "walking through" all three objects
In regards of complexity it always great to break up the application
according to its responsibilities or concerns.
Considering your code, it seems you are following the industry specified standard. For better clarity I am also adding here a sample code snippet of a standard project architecture.
Controller:
[Route("api/User")]
[ApiController]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[HttpGet]
[Authorize]
[Route("users")]
public async Task<ActionResult> Users()
{
var users = await _userService.GetAllUsers();
return Ok(new ResponseViewModel { output = "success", msg = "request successful", returnvalue = users });
}
}
Service Interface:
public interface IUserService
{
Task<List<UserViewModel>> GetAllUsers();
}
Service Implementation:
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public async Task<List<UserViewModel>> GetAllUsers()
{
return await _userRepository.GetAllUsers();
}
}
Repository Interface:
public interface IUserRepository
{
Task<List<UserViewModel>> GetAllUsers();
}
Repository Implementation:
public class UserRepository : IUserRepository
{
private readonly AppDbContext _dbContext;
private readonly IMapper _mapper;
public UserRepository(AppDbContext dbContext, IMapper mapper)
{
_dbContext = dbContext;
_mapper = mapper;
}
public async Task<List<UserViewModel>> GetAllUsers()
{
var users = await _dbContext.Users.ToListAsync();
var userViewModel = _mapper.Map<List<UserViewModel>>(users);
return userViewModel;
}
}
Model:
public class UserViewModel
{
public long user_id { get; set; }
public string full_name { get; set; }
}
Note: Hope above steps guided you accordingly. Additionally, you could also have a look our official document for more information
regarding industry practices.
How do you perform property injection with Simple Injector.
The with Ninject you do is as per bellow:
[Inject]
public IUnitOfWork UnitOfWork { get; set; }
How can I do the equivalent to this with Simple Injector. I tried finding a solution online but had no luck.
Why do I want to use Property Injection?
I want to use property injection to set up unit of work in my base controller so that it will create a new unit of work OnActionExecuting and commit the changes OnResultExecuted. It also means I don't have to pass in the UoW with each new controller I create through the constructor.
Another option is to use the RegisterInitializer method:
container.RegisterInitializer<BaseControllerType>(controller =>
{
controller.UnitOfWork = container.GetInstance<IUnitOfWork>();
}
It keeps all configuration in your composition root and does not pollute your code base with all kinds of attributes.
Update: (as promised)
While this is a direct answer to your question I have to provide you with a better option, because the usage of a base class for this is a IMO not the correct design, for multiple reasons.
Abstract classes can become real PITA classes as they tend to grow towards a god class which has all kinds of cross cutting concerns
An abstract class, especially when used with property injection, hides the needed dependencies.
With focus on point 2. When you want to unit test a controller which inherits from the base controller, you have no way of knowing that this controller is dependent on IUnitOfWork. This you could solve by using constructor injection instead of property injection:
protected abstract class BaseController : Controller
{
protected readonly IUnitOfWork uoW;
protected BaseController (IUnitOfWork uoW)
{
this.uoW = uoW;
}
}
public class SomeController : BaseController
{
public SomeController(IUnitOfWork uoW) : base(uoW) { }
}
While this solves point 2, point 1 is still lurking. The main reason you're wanting this, as you say, is because you do not want to commit your changes in every Action method. Changes must just be saved by the context when the request is done. And thinking about design in this way is a good thing, because Saving changes is, or can be seen as a cross cutting concern and the way you're implementing this is more or less known as AOP.
If it's comes to AOP, especially if you're working with atomic actions in the action methods of your controllers, there is a far better, more SOLID and more flexible design possible which deals with this very nicely.
I'm referring to the Command/Handler pattern which is described in great detail here (also read this for the query part of your application).
With this patterns you don't inject a generic IUnitOfWork abstraction, but inject the specific needed ICommandHandler<TCommand> abstractions.
The action methods would fire the responsible commandhandler for this specific action. All commandhandlers can simple be decorated by a single open-generic SaveChangesCommandHandlerDecorator, 'ValidationDecorator', 'CheckPermissionsDecorator', etc...
A quick example:
public class MoveCustomerCommand
{
public int CustomerId;
public Address NewAddress;
}
public class MoveCustomerCommandHandler : ICommandHandler<MoveCustomerCommand>
{
public void Handle(MoveCustomerCommand command)
{
// retrieve customer from database
// change address
}
}
public class SaveChangesCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> decoratee;
private readonly DbContext db;
public SaveChangesCommandHandlerDecorator(
ICommandHandler<TCommand> decoratee, DbContext db)
{
this.decoratee = decoratee;
this.db = db;
}
public void Handle(TCommand command)
{
this.decoratee.Handle(command);
this.db.SaveChanges();
}
}
// Register as
container.Register(typeof(ICommandHandler<>), new []{Assembly.GetExecutingAssembly() });
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(SaveChangesCommandHandlerDecorator<>));
// And use in controller as
public ActionResult MoveCustomer(int customerId, Address address)
{
var command = new MoveCustomerCommand
{ CustomerId = customerId, Address = address };
this.commandHandler.Handle(command);
return View(new ResultModel());
}
This keeps your controllers clean and let it do what it must do, namely be the layer between the business logic (the commandhandler implementation in this case) and the view.
Need to create the following:
First create the attribute class
[System.AttributeUsage(System.AttributeTargets.Property]
public class Inject : Attribute
{
}
Then create a custom property behavior
class PropertySelectionBehavior<TAttribute> : IPropertySelectionBehavior
where TAttribute : Attribute
{
public bool SelectProperty(Type type, PropertyInfo prop)
{
return prop.GetCustomAttributes(typeof(TAttribute)).Any();
}
}
Finally tell the container to use custom behavior
container.Options.PropertySelectionBehavior = new PropertySelectionBehavior<Inject>();
All that is left to do is decorate the property with the attribute
[Inject]
public IUnitOfWork UnitOfWork { get; set; }
I am started with my first Dapper Dal project.
I have three projects:
- Website (MVC)
- DataLayer (Dapper)
- Model (Poco Classes)
I want to add validation to my model but i also want to use clean poco classes for my datalayer. My datalayer use dapper to map my poco classes to the database.
I have searched the internet but i can't find a good answer.
My question is:
Where do i add my validation?
- In a seppetated project with classes that extend my poco classes or is there a different way?
If you want a clean separation between your DAL classes and your MVC classes, then you can do just that by, for instance, using ViewModels in your MVC-project. The ViewModel would have the properties and validations that works best with what you are presenting in the browser. Your controller would be responsible for mapping the data between the DAL classes and the ViewModels. Automapper is a very good tool for just that.
It would look a bit like the following:
DAL:
public class MyDapperClass
{
public int Id { get; set; }
public string SomeProperty { get; set; }
}
ViewModel:
public class MyViewModelClass
{
public int Id { get; set; }
[StringLength(50),Required]
public string SomeProperty { get; set; }
}
Controller:
// using AutoMapper;
public class MyController : Controller
{
public MyController()
{
// Set up AutoMapper to be able to map your class
Mapper.CreateMap<MyDapperClass, MyViewModelClass>();
}
public ActionResult MyAction()
{
var dalObject = DAL.GetObject();
var viewModel = Mapper.Map<MyViewModelClass>(dalObject);
return View(viewModel);
}
}
I have an MVC application that accesses SQL and Windows Azure. The logical flow looks like this:
Person <--> View <--> Controller.ConvertPersonHere(x) <--> StorageContext.DoDataAction <--> AzurePersonTableEntity
ConvertPersonHere is the answer to this Stack Overflow question and it converts the Model entity to the Storage entity
public class Person
{
public string Name {get;set;}
public int ID {get;set;}
}
public class PersonEntity : TableServiceEntity
{
public string Name {get;set;}
public int ID {get;set;}
// Code to set PartitionKey
// Code to set RowKey
}
Now that I'm adding WCF to the mix, how should I go about accessing data functions? Assume I have currently have a method to .Save(Person) in the controller and want to Save(Person) from my WCF call.
Do I need to abstract out the data actions in the controller?
I would refactor the code like this - move the functionality to convert from Person to PersonEntity and vice versa to a separate mapper, move saving functionality to separate repository as well, and move controller's code for invoking mapper and repository to separate service too.
So methods in your controller will look similar to:
public ActionResult SomeMethod(Person person)
{
if (ModelState.IsValid)
{
_personService.Save(person)
return View("Success");
}
return View();
}
And in your WCF service you'll be able to reuse the code. In order to validate the classes in WCF using DataAnnotations attributes, you can use the approach similar to the following - http://blog.jorgef.net/2011/01/odata-dataannotations.html
From this example, if your Mvc project was gone and replaced by a Wpf project, your other functionality is still available. If you have both projects they can reference core functionality. Have the implementation which has no relation to UI (MVC or WPF) in other projects. This way those UI projects can reference this functionality.
public interface IConverter<TDataModel, TModel> { TModel MapToDomain(TDataModel source);}
public interface IPersonConverter : IConverter<PersonEntity, Person> { }
public interface IPersonRepository { Person GetById(int id); }
public class PersonConverter : IPersonConverter
{
public Person MapToDomain(PersonEntity source)
{
return new Person { ID = source.ID, Name = source.Name };
//or use an AutoMapper implementation
}
}
public class PersonRepository : IPersonRepository
{
private readonly IPersonConverter _personConverter;
public PersonRepository(IPersonConverter personConverter)
{
_personConverter = personConverter;
}
public Person GetById(int id)
{
PersonEntity personEntity = new PersonEntity(); //get from storage
return _personConverter.MapToDomain(personEntity);
}
}
public class MvcController
{
private readonly IPersonRepository _personRepository;
public MvcController(PersonRepository personRepository)
{
_personRepository = personRepository;
}
public ActionResult SomeMethod(int id)
{
Person person = _personRepository.GetById(id);
//make your view model based on the person domain model
//with another convert / map, to fit view as personForm
//(if this is overkill you can use person).
return View(personForm);
}
}
Mvc or Wpf project
PersonForm (ui model)
Controller or Wpf Class
Person -> PersonForm converter
List item
Core project
Person
IPersonRepository
Infrastructure project
Person Repository
Person Entity
Azure Person Table Entity
Storage Context
I know it's a tangent, but if you're mixing WCF and ASP.NET MVC, you should at least be aware of OpenRasta. A good start is this Herding Code podcast with the main contributor.
(No, this is not even intended to answer your actual question!)