NullReference
NullReference

Reputation: 4484

asp.net mvc repository pattern with service layer, when to mix entities in the repositories?

I'm building a new project off the service repository pattern detailed here. It seems to work well in the most basic of examples. In more complex scenarios is it acceptable to mix the objects in the service \ repository layers?. For example say there is a User repository and service and I want to be able to create an audit for the creation of a user, I would think this would go in the service layer.

If I follow the article the service automatically creates the user repository object in the constructor. Adding a audit would mean adding audit CRUD methods to the user repository? Does that make sense to do that?

    public UserService(IValidationDictionary validationDictionary, IUserRrepository repository)
    {
        _validatonDictionary = validationDictionary;
        _repository = repository;
    }

Upvotes: 2

Views: 1567

Answers (2)

Adam Tuliper
Adam Tuliper

Reputation: 30152

You can surely have one repository/service layer handle more than one entity if it falls within the purpose or domain of that service. Generally in simple examples - you are correct, you don't see this but there is no reason you can include another entity.

Now in regards to your audit, why not just call off to your audit service layer instead of including an audit object (if thats what you meant)

Upvotes: 1

np-hard
np-hard

Reputation: 5815

in my experience you dont need repositories for each entity type. Just create one repository for the whole model, and then use linq queries over it. EF already provides implementation of that repository, you can create a custom interface like shown below and implement it over that repository ..

  public interface IDataContext
    {
        void Add<T>(T entity) where T : BaseEntity;
        void Delete<T>(T entity) where T : BaseEntity;
        IQueryable<T> Find<T>(Expression<Func<T, bool>> where) where T : BaseEntity;
        int SaveChanges()
    }

where your base entity is your base class for all repositories.

most of the linq you would write would be pretty straighforward, but for the complicated ones, just write Utility classes

in our implementation the class derived from DbContext implements this interface, and all the auditing is done through the Save Method using the ChangeTracker

A sample implementation of EF 4.2 is below ...

 public class MyContext : DbContext, IDataContext
 {
    static MyContext ()
    {
        Database.SetInitializer<MyContext >(null);
    }

    public T GetById<T>(int id) where T : BaseEntity
    {
        return this.Set<T>().SingleOrDefault(i => i.Id == id);
    }

    public void Add<T>(T entity) where T : BaseEntity
    {
        this.Set<T>().Add(entity);
    }

    public void Delete<T>(T entity) where T : BaseEntity
    {
        this.Set<T>().Remove(entity);
    }

    public IQueryable<T> Find<T>(System.Linq.Expressions.Expression<Func<T, bool>> where) where T : BaseEntity
    {
        return this.Set<T>().Where(where);
    }

    public override int SaveChanges()
    {
        this.SetAuditValues();
        return base.SaveChanges();
    }

   private void SetAuditValues()
    {
        var addedEntries = this.ChangeTracker.Entries().Where(e => e.State ==  System.Data.EntityState.Added);
        var currentUser = this.GetCurrentUser();
        foreach (var addedEntry in addedEntries)
        {
            var entity = addedEntry.Entity as BaseEntity;
            if (entity != null)
            {
                entity.CreateDateTime = DateTime.Now;
                entity.CreateUser = currentUser;
                entity.ModDateTime = DateTime.Now;
                entity.ModUser = currentUser;
            }

        }

        var modifiedEntries = this.ChangeTracker.Entries().Where(e => e.State == System.Data.EntityState.Modified);

        foreach (var modEntry in modifiedEntries)
        {
            var entity = modEntry.Entity as BaseEntity;
            if (entity != null)
            {
                entity.ModDateTime = DateTime.Now;
                entity.ModUser = currentUser;
            }
        }
    }
}

Upvotes: 3

Related Questions