简体   繁体   中英

Generic repository pattern & separation of data layer from business logic

I'm trying to use generic repository pattern (partly based on this article) and while trying to separate my business logic layer and my data layer I'm running into confusion.

This is my repository interface, located in the business logic assembly:

public interface IRepository<TEntity> where TEntity : class
{
    /// <summary>
    /// Get one entity based on its Identifier.
    /// </summary>
    TEntity Get(object id);

    /// <summary>
    /// Get one entity based on provided criteria.
    /// </summary>
    TEntity GetOne(Expression<Func<TEntity, bool>> where = null);

    /// <summary>
    /// Finds entities based on provided criteria.
    /// </summary>
    IQueryable<TEntity> GetAll(Expression<Func<TEntity, bool>> where = null);

    /// <summary>
    /// Insert the existing entity.
    /// </summary>
    void Insert(TEntity model);

    /// <summary>
    /// Deletes the existing entity.
    /// </summary>
    void Delete(long id);

    /// <summary>
    /// Updates the existing entity.
    /// </summary>
    void Update(TEntity model);
}

this is my concreate repository class in my data layer assembly:

 public class EfRepository<TEntity> : IRepository<TEntity>, IDisposable
   where TEntity : class, new() 
{
    private readonly DbContext _context;
    private DbSet<TEntity> _entities;

    internal EfRepository(DbContext context)
    {
        _context = context;
    }

    private DbSet<TEntity> Entities
    {
        get { return _entities ?? (_entities = _context.Set<TEntity>()); }
    }

    public TEntity Get(object id)
    {
        return Entities.Find(id);
    }

    public void Insert(TEntity entity)
    {
        Entities.Add(entity);
        Save();
    }

    public void Delete(long id)
    {
        var entity = Get(id);
        Delete(entity);
    }

    private void Delete(TEntity entity)
    {
        Entities.Remove(entity);
        Save();
    }

    public IList<TEntity> Table
    {
        get { return Entities.ToList(); }
    }

    public void Update(TEntity entity)
    {
        _context.Entry(entity).State = System.Data.EntityState.Modified;
        Save();
    }

    private void Save()
    {
        _context.SaveChanges();
    }

    public void Dispose()
    {
        _context.Dispose();
    }

    public TEntity GetOne(System.Linq.Expressions.Expression<Func<TEntity, bool>> where = null)
    {
        return GetAll(where).FirstOrDefault();
    }

    public IQueryable<TEntity> GetAll(System.Linq.Expressions.Expression<Func<TEntity, bool>> where = null)
    {
        return null != where ? Entities.Where(where) : Entities;
    }
}

and a service from the bussines logic would look like this:

public class UserService : IUserService
{
    private IRepository<User> _userRepository;

    public UserService(IRepository<User> userRepository)
    {
        _userRepository = userRepository;
    }
    public void Register(User user)
    {
        //some logic goes here
        _userRepository.Insert(user);
    }
}

now the problem is that I don't want my business logic to be aware of the data layer, meaning that TEntity should be a business object (like User in this example).

Does it mean I need to map each business object to its data object in the data layer?

I'm not sure if I'm approaching it right, and if i do, how should I do that mapping? cause I'm also stuck with this and that what made me think im approaching it wrong.

In my personal opinion, I won't recommend you to use your business model as your view model. Check this link for more info about it.

Regarding how can you do the object mapping: Check Automapper , it's a nice tool and you can find the documentation on Github and a lot of tutorials like this on internet!

Regards.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM