Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic Repository with EntityFramework

I'd like to implement a generic repository pattern using Entity Framework (I know there are many controversial opinions about repositories, but still this is what I need). The interface I'd like it to have is as follows:

public interface IRepository
{
    IQueryable<TEntity> Query<TEntity>() 
        where TEntity: Entity;

    void Save<TEntity>(TEntity entity) 
        where TEntity : Entity;

    void Delete<TEntity>(TEntity entity) 
        where TEntity : Entity;
}

Entity is a base class that just has an int ID property. And to use it like this:

        IRepository repository = ... // get repository (connects to DB)
        int userId = GetCurrentUserId();
        if (!repository.Query<User>().Any(u => u.Id == userId)) // performs SELECT query
        {    /*return error*/    }

        var newOrder = new Order { UserId = userId, Status = "New" }
        repository.Save(newOrder); // performs INSERT query
        ...
        newOrder.Status = "Completed";
        repository.Save(newOrder); // performs UPDATE query

I'd like to avoid UnitOwWork and just commit all object changes to the DB once Save() or Delete() is called. What I want to do looks really simple, but I haven't found any examples of how to do it using EntityFramework.The closest example I could find is this answer, but it uses UnitOwWork and repository-per-entity, which is more complicated than what I need to do.

like image 506
Nazz Avatar asked Mar 16 '17 10:03

Nazz


People also ask

What is generic repository pattern in Entity Framework?

It is a data access pattern that prompts a more loosely coupled approach to data access. We create a generic repository, which queries the data source for the data, maps the data from the data source to a business entity, and persists changes in the business entity to the data source.

Is the repository pattern useful with Entity Framework Core?

TL;DR – summary. No, the repository/unit-of-work pattern (shortened to Rep/UoW) isn't useful with EF Core. EF Core already implements a Rep/UoW pattern, so layering another Rep/UoW pattern on top of EF Core isn't helpful.

What is Entity Framework repository?

Repository Pattern is used to create an abstraction layer between data access layer and business logic layer of an application. Repository directly communicates with data access layer [DAL] and gets the data and provides it to business logic layer [BAL].

Can I use Entity Framework and dapper together?

Important Aspect to Handle – Transactions Now, according to our requirement, we need both Entity Framework Core and Dapper to work alongside each other. This is quite easy to achieve actually.


2 Answers

1-Create One Interface

interface IMain<T> where T : class
    {
        List<T> GetAll();
        T GetById(int id);
        void Add(T entity);
        void Edit(T entity);
        void Del(int id);
        int Savechange();
    }

2-Create One Class

public class Main<T> : IMain<T> where T : class
    {
        public DataContext db;
        public void Add(T entity)
        {
            db.Set<T>().Add(entity);
        }

        public void Del(int id)
        {
            var q = GetById(id);
            db.Set<T>().Remove(q);
        }

        public void Edit(T entity)
        {
            db.Entry<T>(entity).State = EntityState.Modified;
        }

        public List<T> GetAll()
        {
            return db.Set<T>().Select(a=>a).ToList();
        }

        public T GetById(int id)
        {
            return db.Set<T>().Find(id);
        }

        public int Savechange()
        {
            return db.SaveChanges();
        }
    }

3-Create One Repository With Name YourTable ForExample Student

 public class Student : Main<Tbl_Student>
    {
        public Student()
        {
            db = new DataContext();
        }
    }

4-To Your Action Write This Code

Student student=new Student();
student.Del(3);
int a = student.Savechange();
like image 139
Diako Hasani Avatar answered Sep 29 '22 17:09

Diako Hasani


You can do that with expression keyword;

    public interface IRepository<TEntity> where TEntity : Entity
    {
        IQueryable<TEntity> Query(Expression<Func<TEntity, bool>> predicate);

        void Save(TEntity entity);

        void Delete(TEntity entity);
    }

    public abstract class EfRepository<T> : IRepository<T> where T : Entity
    {
        private readonly DbContext _dbContext;
        protected readonly DbSet<T> _dbSet;
        public EfRepository(YourDbContextContext dbContext)
        {
            _dbContext = dbContext;
            _dbSet = dbContext.Set<T>();
        }

        public void Delete(T entity)
        {
            if (entity == null) return;
            else
            {
                DbEntityEntry dbEntityEntry = _dbContext.Entry(entity);

                if (dbEntityEntry.State != EntityState.Deleted)
                {
                    dbEntityEntry.State = EntityState.Deleted;
                }
                else
                {
                    _dbSet.Attach(entity);
                    _dbSet.Remove(entity);
                    _dbContext.SaveChanges();
                }
            }
        }

        public IQueryable<T> Query(Expression<Func<T, bool>> predicate)
        {
            return _dbSet.Where(predicate);
        }

        public void Save(T entity)
        {
            if (entity.Id > 0)
            {
                _dbSet.Attach(entity);
                _dbContext.Entry(entity).State = EntityState.Modified;
                _dbContext.SaveChanges();
            }
            else
            {
                _dbSet.Add(entity);
                _dbContext.SaveChanges();
            }
        }
    }
    public class Entity
    {
        public int Id { get; set; }
    }

Then create your repositories;

     public interface IUserRepository : IRepository<User>
     {
       //Also you can add here another methods according to your needs
     }
     public class UserRepository : EfRepository<User>,IUserRepository
     {
            public UserRepository(YourDbContext yourDbContext) : base(yourDbContext)
            {

            }
     }

Then use it;

IUserRepository _userRepository => Getit
//If there are entities according to your conditions, this will return them, then use it
_userRepository.Query(u => u.Id == userId);
like image 21
Murat Can OĞUZHAN Avatar answered Sep 29 '22 17:09

Murat Can OĞUZHAN