Skip to content

Instantly share code, notes, and snippets.

@pmbanugo
Last active September 26, 2023 06:46
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save pmbanugo/8456744 to your computer and use it in GitHub Desktop.
Save pmbanugo/8456744 to your computer and use it in GitHub Desktop.
Implementation of the Repository and UnitOfWork pattern using Entity Framework.
// License: Apache 2.0
// A generic base repository which other repositories (if needed) can inherit from
public class BaseRepository<TEntity> : IEntityRepository<TEntity> where TEntity : class
{
internal DataContext context;
internal DbSet<TEntity> dbSet;
public BaseRepository(DataContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, params Expression<Func<TEntity, object>>[] includeProperties)
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetById(params object[] id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
public virtual void Delete(params object[] id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entityToDelete)
{
if (context.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
}
// License: Apache 2.0
//Interface that defines the basis of my repository classes
public interface IEntityRepository<T>
{
IEnumerable<T> Get(Expression<Func<T, bool>> filter = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
params Expression<Func<T, object>>[] includeProperties);
T GetById(params object[] id); //uses params keyword which allows searching tables with composite primary key.
void Insert(T entity);
void Update(T entityToUpdate);
//Deletes the object based on the primary key and uses params to support entities with composite primary key
void Delete(params object[] id);
}
// License: Apache 2.0
public interface IUnitOfWork : IDisposable
{
IAccountRepository AccountRepository { get; }
void Save();
}
// License: Apache 2.0
public class UnitOfWork : IUnitOfWork
{
private bool _disposed = false;
private DataContext _context = new DataContext();
private BaseRepository<User> userRepository;
private AccountRepository accountRepository;
public BaseRepository<User> UserRepository
{
get
{
if (this.userRepository == null)
{
this.userRepository = new GenericRepository<User>(_context);
}
return userRepository;
}
}
public IAccountRepository AccountRepository
{
get
{
if (this.accountRepository == null)
{
this.accountRepository = new AccountRepository(_context);
}
return accountRepository;
}
}
public void Save()
{
_context.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this._disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this._disposed = true;
}
// License: Apache 2.0
//Sample controller class which also show how to use the include parameter options which i a linq query
public class UserController : Controller
{
private UnitOfWork unitOfWork = new UnitOfWork();
public ActionResult Index()
{
//example
var users = unitOfWork.UserRepository.Get(includeProperties: user => user.Followers);
foreach (var user in users)
{
//do something maybe
}
return View(users);
}
protected override void Dispose(bool disposing)
{
unitOfWork.Save();//Saves all unsaved result before disposing
unitOfWork.Dispose();
base.Dispose(disposing);
}
@samirhosseini
Copy link

samirhosseini commented Jan 24, 2020

thanks alot ๐Ÿ™ ,
consider we have a ShoppingCart table that references to Product table and Reduction table.how to write this join? thanks

@pmbanugo
Copy link
Author

I don't understand what you're asking.

@samirhosseini
Copy link

samirhosseini commented Jan 24, 2020

Thanks for your consideration,๐Ÿ™๐Ÿ™๐Ÿ™

At the User controller You've joined user table with one table named "followers",isn't it? So, I wanna join some tables together.for example, three or more tables to be joined.
for simple example,one table joins with men table and women table.
includeProperties: a => a.men, b=>b.women
Is this true?

@pmbanugo
Copy link
Author

Yes it is.

@samirhosseini
Copy link

Thanks alot.๐Ÿ™๐Ÿ˜

@Mdyunus56
Copy link

Mdyunus56 commented Mar 8, 2021

Thanks for the code, can we use this code in any personal, non-commercial, commercial application? looking for license terms. It will be helpful if tag it under some open source license (MIT, Apache etc.) if applicable.

@DANIEL-ASHRAF
Copy link

in function get :
what should I do to add projection(select) after include?

@lasbrojen
Copy link

lasbrojen commented Jan 30, 2022

Thanks alot @pmbanugo ๐Ÿ™I have used some of your code.

How whould you handle ThenInclude()? ๐Ÿ˜

@pmbanugo
Copy link
Author

@Mdyunus56 you can use the code freely

@pmbanugo
Copy link
Author

@lasbrojen I'm not sure. When I wrote this implementation that API/type wasn't available (I think - .NET Framework ). I may have to dig in a bit as I've not really used EF for some years now ๐Ÿ˜…

@Praveen8619
Copy link

@pmbanugo Thanks for your code. Is it tagged under some open source license (MIT, Apache etc.) if applicable ?

@pmbanugo
Copy link
Author

pmbanugo commented May 10, 2023

@Praveen8619 You can use and distribute it freely as you choose. I can't put a License file on GitHub gist.

I just added comments in the code to clarify that

@Praveen8619
Copy link

@Praveen8619 You can use and distribute it freely as you choose. I can't put a License file on GitHub gist.

I just added comments in the code to clarify that

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment