How to decouple repository and entities - model-view-controller

This is a question on domain model design.
Let's say for a domain design involving users and groups, we have the following interfaces to implement:
interface IUser
{
string Name{get;}
DateTime DOB {get;}
}
interface IGroup
{
string Name {get;}
bool IsUserInGroup(IUser user); // #1
void IncludeUser(IUser user); // #2
void ExcludeUser(IUser user); // #3
}
interface IUserRepository
{
IUser Create(string name);
IUser GetByName(string name);
void Remove(IUser user);
void Save(IUser user);
}
interface IGroupRepository
{
IGroup Create(string name);
IGroup GetByName(string name);
void Remove(IGroup group);
void Save(IGroup group);
}
The tricky bit is to implement #1 #2 and #3 while keeping the entity classes (User, Group) decoupled from the repository classes (UserRepository, GroupRepository.)
Another technicality to consider is that most RMDB systems do not implement many-to-many relationships, and in practice there is always a separate table (say, UserGroupAssociation) to have records each associates a user and a group via foreign keys. I would like to hide this implementation detail from the domain interfaces and expose the equivalent logic through members #1 #2 and #3.
The effect of calling #2 and #3 should not persist until the group object in question has been saved (i.e. passed to the Save() method of the repository object)
How do you usually do it?

I don't do it. My Repository objects are tightly coupled to the root of the aggregate to which they relate, and (as kind of an aside) I don't bother making interfaces for my domain model objects unless I find I have a good reason to do so - do you have a particular reason to do this?
I've not come across any Repository examples which don't use the entity implementation type in the repository class (this one, for instance) and can't think of any real advantage of using an interface instead. Interfaces earn their keep for infrastructure components (like a Repository) by making it easier to mock out entire layers of the system when testing, you don't get the same type of advantage using interfaces for domain objects.
And to perhaps actually answer the question...
I never have a domain object access a Repository - the domain object after all is supposed to represent something in the domain in real life, and Repositories are infrastructure components that don't exist in real life, so why would a domain object know about one?
For the specific example of adding a User to a Group, I'd use a Service Layer class, and do this:
public class UserService
{
private readonly IGroupRepository _groupRepository;
private readonly IUserRepository _userRepository;
public UserService(
IGroupRepository groupRepository,
IUserRepository userRepository)
{
this._groupRepository = groupRepository;
this._userRepository = userRepository;
}
public void IncludeUserInGroup(string groupName, string userName)
{
var group = this._groupRepository.FindByName(groupName);
var user = this._userRepository.FindByName(userName);
group.IncludeUser(user);
this._userRepository.SaveChanges();
}
}
public class User
{
public void AddToGroup(Group group)
{
this.Groups.Add(group);
}
public void RemoveFromGroup(Group group)
{
this.Groups.Remove(group);
}
}
Some points to note:
To avoid lazy-loading large numbers of Users when adding a User to a Group I've moved the Group administration methods onto User - depending on how much behaviour you actually have for Group, you might even consider turning it into an enumeration rather than a class. Be aware that if you're using the Entity Framework POCO T4 Templates with FixupCollections, this will still lazy-load all the Users in a Group, but you can get around that in one way or another :)
The Service Layer class would implement a Create() method, the like of which you have on your Repositories. The Repositories would have an Add method, Find methods and a SaveChanges() method. Add would add an object created by the Service Layer to the object context.
All Repository classes would be set up to use the same underlying, request-scoped object context, so it wouldn't matter which one you call SaveChanges() on.
SaveChanges() would cause all changes which had happened to objects during that request to be saved, such as a User having a new Group's added to their Groups collection.
Finally, another good technique for decoupling entities from Repositories and other infrastructure components is Domain Events.

Related

What is the right design to have a spring Entity that is different than what the REST API returns?

Right now, I have an #Entity say Car that has a certain set of attributes. This gets persisted into a database.
Now, in the #RestController, if I want to accept a Car parameter except for certain properties, how do I do that? Right now, I am creating a different class called CarInput that is the same as Car minus those properties.
Again, for REST API response, same thing. If I want to return a Car but with a certain field removed. Right now I created CarResponse as a model.
Is there a cleaner way to do this?
I'd make the case that your external representation and your internal storage should hardly ever be identical. Sure, there'll be significant overlap, but your database and your API should be as independent from each other as possible.
I'd say it's a good practice to have separate domain models for the model and view layer (read: two different Car classes, in different packages). You can use a mapping framework like Dozer or MapStruct to map back and forth between these different entity types.
There are two common approaches to such problem.
Use #JsonIgnore on fields/getters that you want to exclude. However, this can lead to annotation hell or generally hard to read code.
#JsonIgnore
private String password;
Create a DTO class that data would be deserialized from or serialized to. What I mean is that when some user makes a POST request with a car definition, it would be deserialized by spring to CarDto and then parsed by you in the service layer to the Car object which you could save to a database. Similarly, Car object would be parsed to CarDto if the user asks for a data.
#GetMapping("/{userId}")
UserDto getUser(#PathVariable Long userId) {
return userService.getUser(userId);
}
#PostMapping
UserDto addUser(#RequestBody UserDto userDto) {
return userService.createUser(userDto);
}
This one, on the other hand, could lead to a situation where you sometimes use a Dto and sometimes the class itself. Because of that, consider parsing to/from CarDto only in the controller layer (unlike in the example above)
Also it's good to avoid creating two classes in one file. It makes hard to find a desired class afterwards.
You can still avoid of using a DTO class.
When you post Car object to controller your can control the wanted properties and operate on it.
For selecting fields to return as the response you can use json views.
Entity :
public Car {
private String color;
#JsonView(Views.Public.class)
private Integer weight;
// getters, setters
}
Controller :
#RestController
public CarController
#Autowired
private CarRepository carRepository;
#GetMapping("/{id}")
#JsonView(View.Public.class)
public Book get(#PathVariable Long id){
return carRepository.findOne(id);
}
#PostMapping
public Book update(#RequestBody Car car) {
// only properties we want to update
if(car.getColor() != null) {
// save in database or other operations
}
}
}
View :
public class Views {
public static class Public {
}
}
This way the controller's method "get" will send to client only "weight" property and "update" method will operate only on selected properties.

How to inject ISession into Repository correctly?

Please correct me on the following scenario. ( Question is at the end)
(I asked a similar question that was un-organized and it was voted to close. So I have summarized the question here into a scope that can be replied with exact answers.)
I am developing a web application with multiple layers using nhibernate as ORM. My layer structure is as follow
Model Layer
Repository Layer
Services Layer
UI Layer
with the above layers, the classes and interfaces are placed as below.
ProductController.cs (UI Layer)
public class ProductController : Controller
{
ProductServices _ProductServices;
NHibernate.ISession _Session;
public ProductController()
{
_Session = SessionManager.GetCurrentSession();
_ProductServices = new ProductServices(
new ProductRepository(), _Session);
}
// Cont..
}
ProductServices.cs (Service Layer)
public class ProductServices : IProductServices
{
protected IProductRepository _ProductRepository;
protected NHibernate.ISession _Session;
public ProductServices(IProductRepository productRepository,
NHibernate.ISession session)
{
_ProductRepository = productRepository;
_Session = session;
_ProductRepository.SetSession(_Session);
}
// cont...
}
ProductRepository.cs (Repository Layer)
public class ProductRepository : IProductRepository
{
NHibernate.ISession _Session;
public void SetSession(NHibernate.ISession session)
{
_Session = session;
}
public IEnumerable<Product> FindAll()
{
return _Session.CreateCriteria<Product>().List<Product>();
}
//cont..
}
From the UI layer, I create the session as request per session and inject into service layer with the help of class constructor. Then set the session of repository with a help of a method.
I am afraid if I pass the _Session directly to repository as constructor, I will not have the control over it under the service layer. Also there is a future extension plan for using a webservice layer.
** Is there a way to ensure in each method of ProductRepository class that _Session is set already, without writing the piece of code if(_Session==null) in each and every method as it is repeating the same code.
** If the above pattern is wrong, Please show me a right way to achieve this goal.
What you are doing amazed me a bit. You applying the constructor injection pattern in the ProductService, which is definitely the way to go. On the other hand you are not injecting the dependencies into the ProductController, but that class is requesting one of those dependencies through a static class (this is the Service Locator anti-pattern) and creates a ProductServices class itself. This makes this class hard to test and makes your application less flexible and maintainable, since you can't easily change, decorate or intercept the use of the ProductServices class, when it's been used in multiple places.
And although you are (correctly) using constructor injection for the dependencies in the ProductServices, you are passing those dependencies on to the product repository, instead of applying the constructor injection pattern on the ProductResopistory as well.
Please show me a right way to achieve this goal.
The right way is to apply the constructor injection pattern everywhere. When you do this, your code will start to look like this:
public class ProductController : Controller
{
private ProductServices _ProductServices;
public ProductController(ProductServices services)
{
_ProductServices = services;
}
// Cont..
}
public class ProductServices : IProductServices
{
private IProductRepository _ProductRepository;
public ProductServices(
IProductRepository productRepository)
{
_ProductRepository = productRepository;
}
// cont...
}
public class ProductRepository : IProductRepository
{
private ISession _Session;
public ProductRepository (ISession session)
{
_Session = session;
}
public IEnumerable<Product> FindAll()
{
return _Session
.CreateCriteria<Product>().List<Product>();
}
//cont..
}
See how each class only takes in dependencies that it uses itself. So the ProductController and ProductServices don't depend on ISession (I made the assumption that only ProductRepoistory needs ISession). See how -from a class's perspective- everything is much simpler now?
Did we actually solve a problem here? It seems like we just moved the problem of wiring all classes together up the dependency graph. Yes we did move the problem. And this is a good thing. Now each class can be tested in isolation, is easier to follow, and the application as a whole is more maintainable.
Somewhere in the application however, a ProductController must be created. This could look like this:
new ProductController(
new ProductServices(
new ProductRepository(
SessionManager.GetCurrentSession())));
In its normal configuration, ASP.NET MVC will create controller classes for you, and it needs a default constructor to do so. If you want to wire up controllers using constructor injection (which you should definitely do), you need to do something 'special' to get this to work.
ASP.NET MVC allows you to override the default ControllerFactory class. This allows you to decide how to create controller instances. However, when your application starts to grow, it will get really awkward very quickly when you are creating your dependency graphs by hand (as my last example shows). In this case, it would be much better to use a Dependency Injection framework. Most of them contain a feature / package that allows you to integrate it with ASP.NET MVC and automatically allows to use constructor injection on your MVC controllers.
Are we done yet? Well... are we ever? There's one thing in your design that triggered a flag in my brain. Your system contains a class named ProductServices. Although a wild guess, the name Services seems like you wrapped all product related business operations inside that class. Depending on the size of your system, the number of people on your team, and the amount of changes you need to make, this might get problematic. For instance, how to you effectively apply cross-cutting concerns (such as logging, validation, profiling, transaction management, fault tolerance improvements) in such way that to system stays maintainable?
So instead of wrapping all operations in a single ProductServices class, try giving each business transaction / use case its own class and apply the same (generic) interface to all those classes. This description might be a bit vague, but it is a great way to improve the maintainability of small and big systems. You can read more about that here.
You can use a dependency injection container such as Autofac to instantiate your session and manage the lifetime of it. Leave the responsibility of instantiating the session to Autofac and simply inject the ISession interface into any classes that require the dependency. Have a look at this post: Managing NHibernate ISession with Autofac
You will also find this wiki page useful about configuring Autofac with MVC3: http://code.google.com/p/autofac/wiki/MvcIntegration3

Is there a recommended base repository class to use with Entity Framework?

I'm using an EF Code First approach with an ASP.NET MVC 3 application, and instead of re-creating the wheel, I was wondering if there already exists a solid base Repository class that my custom Repository classes could extend in order to provide default functionality out of the box (e.g. basic CRUD, etc...).
So something like this ...
public class CustomerRepository : BaseRepository { ... }
... would therefore provide a default way to work with Customer objects out of the box. I'd like to then inject an ICustomerRepository into my MVC controllers and have the functionality available to me there.
I'm sure something like this already exists out there as I've done something similar with NHibernate.
Thanks
No, there is no built-in repository, other than EF itself (which is in and of itself an implementation of the Unit of Work pattern, and DbSet's are basically Repositories).
There is currently a debate in the software community over whether generic repositories have much real value. For testing purposes, many argue, they provide easy unit testing. Others say that unit testing repositories doesn't help because mocked repositories don't behave the same way that real ones do (because of the linq -> Sql translation layer, which doesn't exist in a mocked repository).
Many are suggesting that you do integration testing against EF using an in-memory database like SqlLite rather than unit testing it.
Still, if you are intent on using repositories, there are many examples out there on the net, with varying styles and methods. Or you can roll your own. MS does not provide one.
In my experience, write your own repositories is redundant because EF implements this pattern already through DbSet's.
I worked with MVC3 + EF Code Fisrt in a recent project. We started implementing a generic repository following some tutorials and soon we realized that we are writing a lot of unnecessary and redundant code. Actually, the repositories were given us nothing but hiding a lot of the DbSet's functionality. Finally, we decided to remove them and work with our DbContext and DbSet's directly.
But, how about complex business logic beyond simple CRUD operations?
Well, we exposed all complex functionality like queries and multiple CRUD operations through a service layer. You can build different service classes by functionality. By example, you can write an AccountService to manage all functionality related with user accounts. Something like this:
public class AccountService {
private MyContext ctx;
public AccountService(DbContext dbContext) {
this.ctx = (MyContext)dbContext;
}
/// <summary>
/// Gets the underlying DbContext object.
/// </summary>
public DbContext DbContext {
get { return ctx; }
}
/// <summary>
/// Gets the users repository.
/// </summary>
public DbSet<User> Users {
get {return ctx.Users;}
}
public bool ValidateLogin(string username, string password) {
return ctx.Users.Any(u => u.Username == username && u.Password == password);
}
public string[] GetRolesForUser(string username) {
var qry = from u in ctx.Users
from r in u.Roles
where u.Username == username
select r.Code;
return qry.ToArray<String>();
}
public User CreateUser(string username, string password) {
if (String.IsNullOrWhiteSpace(username)) throw new ArgumentException("Invalid user name");
if (String.IsNullOrWhiteSpace(password)) throw new ArgumentException("Invalid password");
User u = new User {
Username = username.Trim().ToLower(),
Password = password.Trim().ToLower(),
Roles = new List<Role>()
};
ctx.Users.Add(u);
ctx.SaveChanges();
return u;
}
How about dependency injection?
Using this approach, the only thing we need to inject is the DbContext. The service classes has a constructor that takes a DbContext. So, when your controller constructor takes a service instance the DbContext will be injected to it.
Edit: Example code
This is an example code about how you controller could look:
public class HomeController : Controller {
private readonly AccountService accountService;
public AccountController(AccountService accountService) {
this.accountService = accountService;
}
}
And this could be the DI configuration using NInject:
private static void RegisterServices(IKernel kernel) {
kernel.Bind<MyContext>().ToSelf().InRequestScope();
kernel.Bind<DbContext>().ToMethod(ctx => ctx.Kernel.Get<MyContext>());
}
How about unit testing?
You could build specific interfaces for each service layer class and mock it where you need.
A friend of mine, Sacha Barber wrote a nice article covering some of these ideas.
Link can be found here.
RESTful WCF / EF POCO / Unit of Work / Repository / MEF: 1 of 2
EF has a base class called DbContext. You can add properties of type DbSet<TEntity>
This allows you to do something like this:
public class User {
public int Id { get; set; }
public string Name { get; set; }
}
public class DatabaseContext : DbContext {
public DbSet<User> Users { get; set; }
}
You can now use this like so:
using(var db = new DatabaseContext()) {
User jon = new User {Name = "Jon Smith"};
db.Users.Add(jon);
db.SaveChanges();
var jonById = db.Users.Single(x => x.Id == 1);
}
If you want more abstraction see this post about building a generic repository around EF Entity Framework 4 CTP 4 / CTP 5 Generic Repository Pattern and Unit Testable Just to note, this level of abstraction is not always needed. You should decide if your abblication will truly benefit from adding a generic repository over just using DbContext directly.

ASP.Net MVC 3 - What is the best way to get logged-in username from within the repository?

I know that you can get the username of the currently logged in user from within the controller by using User.Identity.Name. However, my solution is split in 4 layers (4 projects):
MyProject.Domain for the models
MyProject.Data for the repositories
MyProject.Services where the business logic is
MyProject.Web for the controllers, the ViewModels and the Views
Now, my question is what is the best way the get the username of the current user from within the repository.
The thing is that all my models have 4 audit properties: CreatedBy, CreatedDate, ModifiedBy, ModifiedDate. And I am wondering how to populate the CreatedBy and the ModifiedBy properties when a model is stored to the database.
UPDATE:
Here is what I did following the advices I got below. I added an IUser interface in my Domain. I am not sure whether this is the best place to add this, but I decided to put it there, since my domain in referenced by all my other layers. I also added a User class to my controller layer (MyProject.Web), since this class needs access to the HttpContext, and this is the layer where it is accessible. To tell the truth, I did not know where such a class should be added in this layer. I have a Lib directory, so I put it in there.
Then I added a binding in MyProject.Web.App_Start.NinjectMVC3 like this:
private static void RegisterServices(IKernel kernel)
{
...
kernel.Bind<IUser>().To<User>();
}
I also added an IUser parameter to my base repository class constructor like this:
public abstract class RepositoryBase<T> where T : class, IEntity
{
#region Members
private UpDirContext dataContext;
private readonly IDbSet<T> dbset;
private readonly IUser user;
#endregion
protected RepositoryBase(IDatabaseFactory databaseFactory, IUser user)
{
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
this.user = user;
}
...
So now, I can use "user" everywhere in my repositories. It is working, but I am not sure whether this is the best way of structuring things.
I also thought that I could use injection to pass IUser to my base entity class and make sure that the CreatedBy and ModifiedBy properties of my entities would be populated properly from the start, meaning object construction, but then my entities would not have had a constructor with zero parameter, and I did not want that.
UPDATE 2:
Here is an example of one of my services constructor:
public partial class SectorService : ISectorService
{
private readonly ISectorRepository sectorRepository;
private readonly IUnitOfWork unitOfWork;
public SectorService(ISectorRepository sectorRepository, IUnitOfWork unitOfWork)
{
this.sectorRepository = sectorRepository;
this.unitOfWork = unitOfWork;
}
...
I already use injections to get the repositories to the service layer. According to a comment below, IUser should be injected to the service layer, and I am wondering what is the best method to get User passed from this layer to the repositories.
Using dependency injection, inject an IUser at your composition root (ie your controller's constructor - all the main DI containers support it plius mvc supports it). The concrete implementation of IUser references HttpContext.Current.User.Identity.Name. All of the receivers of IUser don't need to care about where it came from.
I'm not following why though you asked about createdby, etc. Is this a separate question or are you referring to membership information?
My practice as of late is to pass it from controller -> service, then service -> repository, if necessary. This is because I want two websites (think public facing website and private API website) to use the same models/repositories/services, but the authentication methods for each are different.

How to execute Queries with multiple models in Entity framework with Dependency Injection

I tried using Dependency Injection with Entity framework in my MVC application. In the project I have defined Generic Repository class for CRUD operations. There are concrete service classes for each model object. My Controller in Presentation layer uses Concrete classes of Service layer to get data from database. These concrete classes in turn calls RepositoryClass methods to implement actual operation with database.
Below is sample of the class definations (for simplicity I have removed various interfaces details and implementation of some methods):
class RepositoryBase<T>
{
Add(T entity) {...}
Update (T entity) {...}
Delete (T entity) {...}
T GetById(int id) {...}
IEnumerable<T> GetAll()
{dbContext.ToList();}
}
public class CarsService {
public IEnumerable<Cars> GetCars()
{
var cars = RepositoryBase<Cars>.GetAll();
return cars;
}
public Car GetCar(int id)
{
var car = RepositoryBase<T>.GetById(id);
return car;
}
}
Public class DealerService {...}
All this works great as long as I have to deal with 1 object type at a time in my application. But I am not sure how to make change in service class to get data for multiple entities i.e. Car and dealers togather. Please note in my scenario although i have dealer id defined in Cars model but navigation property is missing. So I have to join Cars and Dealers using linq query.
Please help to identify correct class (layer) which needs to be modified. All the examples I have found only talks about 1 entity at a time.
DbContext.Set().Include()first of all you put you config mapping for fixing,
second if you don't want to use navigation properties , you can use
RepositoryBase<Cars>.GetEntitySet<Cars>.Include("Dealers") //this does join if you key to join
but in this case you should use the
add to RepositoryBase<T> a property
public ISet<T> GetEntitySet<T>(string table2Include)
{
return DbContext.Set<T>()
}

Resources