patterncsharpMinor
Service-Repository pattern with IoC, NPoco micro-ORM and unit tests
Viewed 0 times
microiocwithormtestsnpocoservicerepositoryandpattern
Problem
I'm trying to build a Web API using best practices, based on a simple proof-of-concept using students.
My goal is to build the system using:
One thing I'd like to add is a Unit Of Work using database transactions.
Please tell me what you think so I can expand my knowledge and get better.
Project is on GitHub.
Project consists of:
DAL
Starting with the Student entity using NPoco filters/decorators:
My interface for the Student Repository:
My DbFactory interface, to get the NPoco database connection object:
My DbFactory implementation:
My Student Repository, injected with the DbFactory:
```
public class StudentRepository : IStudentR
My goal is to build the system using:
- Onion Architecture to seperate concerns.
- Service-Repository for interaction between BLL and DAL.
- Autofac for IoC, to control injected dependencies.
- NPoco for micro-ORM.
- Moq for mocking dependencies in unit tests.
One thing I'd like to add is a Unit Of Work using database transactions.
Please tell me what you think so I can expand my knowledge and get better.
Project is on GitHub.
Project consists of:
- Common library containing DTO's and exceptions that are reused between BLL and API layer.
- DAL library containing everything for data access: Entities, repositories and a database factory.
- BLL library containing all services that the API layer uses.
- API library containing everything for the HTTP layer: Controllers, IoC containers, etc.
DAL
Starting with the Student entity using NPoco filters/decorators:
[TableName("Students")]
public class Student
{
[Column("ID")]
public int ID { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Age")]
public int Age { get; set; }
}My interface for the Student Repository:
public interface IStudentRepository
{
List GetAllStudents();
Models.Entities.Student GetStudentByID(int id);
void AddStudent(Models.Entities.Student student);
}My DbFactory interface, to get the NPoco database connection object:
public interface IDbFactory
{
IDatabase GetConnection();
}My DbFactory implementation:
public class DbFactory : IDbFactory
{
private readonly string _connectionString;
public DbFactory(string connectionString)
{
_connectionString = connectionString;
}
public IDatabase GetConnection()
{
return new Database(_connectionString);
}
}My Student Repository, injected with the DbFactory:
```
public class StudentRepository : IStudentR
Solution
Initial and General Thoughts
Good job!
Source control - I find it easier to handle if packages not there, especially on a slow connection
I generally use this .gitignore file for this type of project https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
and to clear out files easily that are currently in a repo I'd use this method:
https://stackoverflow.com/questions/1139762/ignore-files-that-have-already-been-committed-to-a-git-repository
Can then run consolidate and update on packages (there is a newer version of NPoco.. from 2 to 3). Right click on solution and manage packages
I've put up my refactored code here:
https://bitbucket.org/davemateer/perfectpattern/overview
Pipeline
Continuous Integration - sanity check of a project. I generally always do this. Your code built fine first try on my machine - however this is not always the case. I use Appveyor as it is free for public repos. The only change I had to make from their default setup was:
in build section, before build script, appveyor-retry nuget restore
https://ci.appveyor.com/project/djhmateer/perfectpattern
it runs your tests (your project is running fine)
Code
organse and get rid of unused usings (alt e i o a)
removed unused references:
http://deanhume.com/home/blogpost/visual-studio---why-should-i-remove-unused-references-/6102
careful of the web project - tend to leave that alone
Student namespace
I recommend not having the namespace and the entity name the same:
was: namespace PerfectPattern.DAL.Models.Entities.Student
now: namespace PerfectPattern.DAL.Models.Entities
so, don't have to reference Models.Entities.Student everywhere
to
BLL/DAL and DTO's
So now this is pure opinion on how to do things, and there is no 'Perfect Pattern' :-) Every project has different needs. I have been trying recently using a flatter structure, essentially combining the BLL/DAL together. This negates the pass through code I see a lot in legacy BLL layers.
Regarding DTO's - I now use a ViewModel naming convention, and generally have 1 VM for each 'page' (if you were using a website):
What is not there
Setup deployment to 'prod'. In your case I'd put up an azurewebsite.net site and get appveyor deploying there automatically. This would prove you can deploy to a prod environment. It also gets you thinking about database changes and how to handle it.
If you look at the output of this build project
https://ci.appveyor.com/project/djhmateer/booktech
You'll see I do a build, deploy an MSSQL database locally, run unit and integration tests, then deploy the database changes (as long as no data loss occurs) and code to Azure.
Database Project
I like the DB to be under source control.
eg https://bitbucket.org/davemateer/booktech/src
DB Profiling
I like MiniProfiler - helps me a lot in developing projects with significant data.
I generally use Dapper for micro ORMS.. interesting to see NPoco!
Closing thoughts / Architecture
I work in enterprise software, and generally make my software only as complex as it needs to be. Generally because it will last for many years, with many developers looking at it. I make this point because your codebase is easy to understand currently, so depending on the actual application, you may not want to add any other parts. In fact, using 'Pure DI' instead of an IoC would be a thought (contentious)! http://blog.ploeh.dk/2012/11/06/WhentouseaDIContainer/
Hope this helps.
Good job!
- Built fine
- Tests all passed
- I like the project structure and naming
Source control - I find it easier to handle if packages not there, especially on a slow connection
- Use nuget package restore
I generally use this .gitignore file for this type of project https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
and to clear out files easily that are currently in a repo I'd use this method:
https://stackoverflow.com/questions/1139762/ignore-files-that-have-already-been-committed-to-a-git-repository
Can then run consolidate and update on packages (there is a newer version of NPoco.. from 2 to 3). Right click on solution and manage packages
I've put up my refactored code here:
https://bitbucket.org/davemateer/perfectpattern/overview
Pipeline
Continuous Integration - sanity check of a project. I generally always do this. Your code built fine first try on my machine - however this is not always the case. I use Appveyor as it is free for public repos. The only change I had to make from their default setup was:
in build section, before build script, appveyor-retry nuget restore
https://ci.appveyor.com/project/djhmateer/perfectpattern
it runs your tests (your project is running fine)
Code
organse and get rid of unused usings (alt e i o a)
removed unused references:
http://deanhume.com/home/blogpost/visual-studio---why-should-i-remove-unused-references-/6102
careful of the web project - tend to leave that alone
Student namespace
I recommend not having the namespace and the entity name the same:
was: namespace PerfectPattern.DAL.Models.Entities.Student
now: namespace PerfectPattern.DAL.Models.Entities
so, don't have to reference Models.Entities.Student everywhere
public interface IStudentRepository
{
List GetAllStudents();
Models.Entities.Student GetStudentByID(int id);
void AddStudent(Models.Entities.Student student);
}to
public interface IStudentRepository
{
List GetAllStudents();
Student GetStudentByID(int id);
void AddStudent(Student student);
}BLL/DAL and DTO's
So now this is pure opinion on how to do things, and there is no 'Perfect Pattern' :-) Every project has different needs. I have been trying recently using a flatter structure, essentially combining the BLL/DAL together. This negates the pass through code I see a lot in legacy BLL layers.
Regarding DTO's - I now use a ViewModel naming convention, and generally have 1 VM for each 'page' (if you were using a website):
- studentDTO would become StudentHomePageViewModel
What is not there
Setup deployment to 'prod'. In your case I'd put up an azurewebsite.net site and get appveyor deploying there automatically. This would prove you can deploy to a prod environment. It also gets you thinking about database changes and how to handle it.
If you look at the output of this build project
https://ci.appveyor.com/project/djhmateer/booktech
You'll see I do a build, deploy an MSSQL database locally, run unit and integration tests, then deploy the database changes (as long as no data loss occurs) and code to Azure.
Database Project
I like the DB to be under source control.
eg https://bitbucket.org/davemateer/booktech/src
DB Profiling
I like MiniProfiler - helps me a lot in developing projects with significant data.
I generally use Dapper for micro ORMS.. interesting to see NPoco!
Closing thoughts / Architecture
I work in enterprise software, and generally make my software only as complex as it needs to be. Generally because it will last for many years, with many developers looking at it. I make this point because your codebase is easy to understand currently, so depending on the actual application, you may not want to add any other parts. In fact, using 'Pure DI' instead of an IoC would be a thought (contentious)! http://blog.ploeh.dk/2012/11/06/WhentouseaDIContainer/
Hope this helps.
Code Snippets
public interface IStudentRepository
{
List<Models.Entities.Student> GetAllStudents();
Models.Entities.Student GetStudentByID(int id);
void AddStudent(Models.Entities.Student student);
}public interface IStudentRepository
{
List<Student> GetAllStudents();
Student GetStudentByID(int id);
void AddStudent(Student student);
}Context
StackExchange Code Review Q#122010, answer score: 5
Revisions (0)
No revisions yet.