In a project, we use generic repository and generic manager so we don't need to rewrite every update / delete etc method in every repository / manager.
Here is how they looks :
public interface IBaseRep<T> : IDisposable where T : class, PrivateObject
{
DbSet<T> DatabaseSet { get; set; }
DbContext Dal { get; set; }
T Find(int? id);
T Find(Expression<Func<T, bool>> predicate);
ICollection<T> Select(Expression<Func<T, bool>> predicate = null,
Expression<Func<T, string>> orderBy = null,
string includeProperties = "");
T Create(T obj);
T Update(T obj);
bool Delete(T obj);
bool Delete(int id);
bool Delete(Expression<Func<T, bool>> predicate);
IQueryable<T> SelectAsQuery(
Expression<Func<T, bool>> predicate = null,
Expression<Func<T, string>> orderBy = null,
string includeProperties = "");
}
public class BaseRep<T> : IBaseRep<T> where T : class, PrivateObject
{
public DbSet<T> DatabaseSet { get; set; }
public DbContext Dal { get; set; }
public EORTCBaseRep(DbContext dal)
{
this.Dal = dal;
this.DatabaseSet = Dal.Set<T>();
}
public virtual T Find(int? id)
{
return this.DatabaseSet.Find(id);
}
public virtual T Find(Expression<Func<T, bool>> predicate)
{
return Select(predicate).FirstOrDefault();
}
public virtual ICollection<T> Select(
Expression<Func<T, bool>> predicate = null,
Expression<Func<T, string>> orderBy = null,
string includeProperties = "")
{
return SelectAsQuery(predicate, orderBy, includeProperties).ToList();
}
public virtual IQueryable<T> SelectAsQuery(
Expression<Func<T, bool>> predicate = null,
Expression<Func<T, string>> orderBy = null,
string includeProperties = "")
{
IQueryable<T> query = this.DatabaseSet;
if (predicate != null)
query = query.Where(predicate);
foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
query = query.Include(includeProperty);
if (orderBy != null)
query = query.OrderBy(orderBy);
return query;
}
public virtual T Create(T obj)
{
this.Dal.Entry<T>(obj).State = EntityState.Added;
this.Dal.SaveChanges();
return obj;
}
public virtual T Update(T obj)
{
this.Dal.Entry<T>(obj).State = EntityState.Modified;
this.Dal.SaveChanges();
return obj;
}
public virtual bool Delete(T obj)
{
if (obj is ILogicallyDeletable)
{
this.Dal.Entry<T>(obj).State = EntityState.Modified;
(obj as ILogicallyDeletable).IsDeleted = true;
}
else
{
this.Dal.Entry<T>(obj).State = EntityState.Deleted;
}
return this.Dal.SaveChanges() == 1;
}
public virtual bool Delete(int id)
{
T obj = Find(id);
return Delete(obj);
}
public virtual bool Delete(Expression<Func<T, bool>> predicate)
{
foreach (T item in Select(predicate))
{
Delete(item);
}
return this.Dal.SaveChanges() == 1;
}
public virtual void Dispose()
{
this.Dal.Dispose();
}
}
Our managers looks like this :
public interface IBaseManager<T> : IDisposable where T : class, PrivateObject
{
T Find(int? id);
T Find(Expression<Func<T, bool>> predicate);
ICollection<T> Select(Expression<Func<T, bool>> predicate = null,
Expression<Func<T, string>> orderBy = null,
string includeProperties = "");
T Create(T obj);
T Update(T obj);
bool Delete(T obj);
bool Delete(int id);
bool Delete(Expression<Func<T, bool>> predicate);
IQueryable<T> SelectAsQuery(
Expression<Func<T, bool>> predicate = null,
Expression<Func<T, string>> orderBy = null,
string includeProperties = "");
}
public class BaseManager<T> : IBaseManager<T> where T : class, PrivateObject
{
protected IBaseRep<T> Repository;
public virtual T Find(int? id)
{
return this.Repository.Find(id);
}
public virtual T Find(Expression<Func<T, bool>> predicate)
{
return this.Repository.Find(predicate);
}
public virtual ICollection<T> Select(
Expression<Func<T, bool>> predicate = null,
Expression<Func<T, string>> orderBy = null,
string includeProperties = "")
{
return this.Repository.Select(predicate, orderBy, includeProperties);
}
public virtual IQueryable<T> SelectAsQuery(
Expression<Func<T, bool>> predicate = null,
Expression<Func<T, string>> orderBy = null,
string includeProperties = "")
{
return this.Repository.SelectAsQuery(predicate, orderBy, includeProperties);
}
public virtual T Create(T obj)
{
return this.Repository.Create(obj);
}
public virtual T Update(T obj)
{
return this.Repository.Update(obj);
}
public virtual bool Delete(T obj)
{
return this.Repository.Delete(obj);
}
public virtual bool Delete(int id)
{
return this.Repository.Delete(id);
}
public virtual bool Delete(Expression<Func<T, bool>> predicate)
{
return this.Repository.Delete(predicate);
}
public virtual void Dispose()
{
if (this.Repository != null)
this.Repository.Dispose();
}
}
This works well.
But, we now need to use the same DB table for multiple entity type :
public abstract class AbstractSite : PrivateObject, IActivable, ILogicallyDeletable
{
public int Id { get; set; }
}
public class EthicCommittee : AbstractSite
{
public int Number { get; set; }
}
public class Site : AbstractSite
{
public string Name { get; set; }
}
This is how we use the generic managers :
public class AbstractSiteManager : BaseManager<AbstractSite>
{
public AbstractSiteManager (PrismaDAL prismaDAL = null)
{
this.Repository = new AbstractSiteRep(prismaDAL);
}
}
and how we use the generic repositories :
public class AbstractSiteRep : PrismaBaseRep<AbstractSite>
{
public AbstractSiteRep (PrismaDAL prismaDAL = null)
: base(prismaDAL)
{}
}
public class PrismaBaseRep<T> : BaseRep<T> where T : class, PrivateObject
{
public PrismaBaseRep(PrismaDAL prismaDAL = null) : base((prismaDAL == null) ? new PrismaDAL() : prismaDAL)
{ }
}
But now, we would like to use the concrete types and not the abstract type anymore (AbstractSite = abstract; Site = concrete, RecruitingInstitution = concrete...) without touching the generic repository / manager. So we would have X generic repository (where X : number of concrete types). All of them pointing to the same DB table.
This would allow us to avoid a cast and allow us to restrict which type we can manipulate using one manager / repository.
Do you, guys, have any idea how i could accomplish this ?
Resolved
My mistake.
This works fine as #Mike C said.
I just didn't know that EF was able to find the correct table if i was referencing a concrete object type instead of the abstract (in TPH).
Related
I currently have a method that allows me to generate an IEnumerable object for my dropdown list in my web app forms.
Example of current code :
//Name with Id
StateListDp = _db.States.ToDropdownList(c => c.Name, c => Convert.ToString(c.Id, CultureInfo.InvariantCulture));
//Description with Id
StatusesListDp = _db.Statuses.ToDropdownList(c => c.Description, c => Convert.ToString(c.Id, CultureInfo.InvariantCulture));
I've just implemented Repository Design Pattern.
I'm able to convert it over to this now :
StateListDp = unitOfWork.State.GetDropDownList().ToList();
StatusesListDp = unitOfWork.Status.GetDropDownList().ToList();
I've created the following support class (I've excluded the unitOfWork for now )
public class StatusRepository : Repository<Statuses>, IStatusRepository
{
private readonly TenDDbContext context;
public StatusRepository(TenDDbContext context): base(context)
{
this.context = context;
}
public IEnumerable<Statuses> GetAllActive()
{
return Find(x => x.IsActive == true);
}
public IEnumerable<SelectListItem> GetDropDownList()
{
return GetAllActive()
.ToDropdownList(c => c.Description, c => Convert.ToString(c.Id, CultureInfo.InvariantCulture));
}
}
public class StateRepository : Repository<States>, IStateRepository
{
private readonly TenDDbContext context;
public StateRepository(TenDDbContext context): base(context)
{
this.context = context;
}
public IEnumerable<States> FindAllActive(Expression<Func<States, bool>> predicate)
{
return Find(predicate).Where(x => x.IsActive == true);
}
public IEnumerable<States> GetAllActive()
{
return Find(x => x.IsActive == true);
}
public IEnumerable<SelectListItem> GetDropDownList()
{
return GetAllActive()
.ToDropdownList(c => c.Name, c => Convert.ToString(c.Id, CultureInfo.InvariantCulture));
}
}
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly TenDDbContext context;
public Repository(TenDDbContext context)
{
this.context = context;
}
public TEntity Add(TEntity entity)
{
return context.Set<TEntity>().Add(entity).Entity;
}
//public bool save(TEntity entity)
//{
// var test= Add(entity);
// test.
//}
public void AddRange(IEnumerable<TEntity> entities)
{
context.Set<TEntity>().AddRange(entities);
}
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return context.Set<TEntity>().Where(predicate);
}
public TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate)
{
return context.Set<TEntity>().SingleOrDefault(predicate);
}
public TEntity Get(int id)
{
return context.Set<TEntity>().Find(id);
}
public IEnumerable<TEntity> GetAll()
{
return context.Set<TEntity>().ToList();
}
public TEntity Update(TEntity entity)
{
//context.Attach(entity).State = EntityState.Modified;
// context.Attach(entity);
//return context.Entry(entity).State = EntityState.Modified;
return context.Update(entity)
.Entity;
}
public void Remove(TEntity entity)
{
context.Set<TEntity>().Remove(entity);
}
public void RemoveRange(IEnumerable<TEntity> entities)
{
context.Set<TEntity>().RemoveRange(entities);
}
}
So my issue is that I have 10 or so tables that I will need to retrieve this very similar data from.
I'm wondering there is a way to make the GetDropDownList a generic method?
So that I can limit the amount of repeat code ...
I'm even willing to make it two methods
GetDropDownNameList and GetDropDownDescriptionList
adding dropdownextension method
public static IEnumerable<SelectListItem> ToDropdownList<T>(this IEnumerable<T> items,
Func<T, string> text, Func<T, string> value = null, Func<T, Boolean> selected = null)
{
var listData = items.Select(p => new SelectListItem
{
Text = text.Invoke(p),
Value = (value == null ? text.Invoke(p) : value.Invoke(p)),
Selected = selected != null && selected.Invoke(p)
});
var defaultRow = new SelectListItem() { Value = "0", Text = "Please Select One", Selected = V };
var newList = listData.Prepend(defaultRow);
//return new SelectList(newList, "Value", "Text");
return newList;
}
passing the selection of the props for description and key should do the trick. If you want to make it even more generic to be inside the IRepository, replace GetAllActive() with a filter
public IEnumerable<SelectListItem> GetDropDownList(Expression<Func<TEntity, string>> predicateDescription, Expression<Func<TEntity, string>> predicateKey)
{
return GetAllActive().ToDropdownList(predicateDescription, predicateKey);
}
I know having a Unit Of Work is having an abstraction on top of an abstraction (DbContext) and surely that is an anti-pattern, or at least is not necessary.
I have the following problem:
I have a generic IRepository like so:
public interface IGenericRepository<TEntity> where TEntity : class
{
IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "");
TEntity GetByID(object id);
void Insert(TEntity entity);
void Delete(object id);
void Delete(TEntity entityToDelete);
void Update(TEntity entityToUpdate);
}
and this is the implementation of this interface:
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
internal GymHelperContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(GymHelperContext context)
{
this.context = context;
dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Delete(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);
}
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
I have a proyect called Facade that instantiates a Mapper and a UnitOfWork, like so:
public class MuscleFacade
{
private readonly UnitOfWork _unitOfWork = new UnitOfWork();
private readonly MuscleMapping _muscleMapping = new MuscleMapping();
public MuscleFacade()
{
}
public IEnumerable<MuscleViewModel> GetAllMuscles()
{
var source = _unitOfWork.MuscleRepository
.Get()
.ToList();
var result = source.Select(x => _muscleMapping.MuscleToModel(x));
return result;
}
public GymViewModel GetGymViewModel()
{
GymViewModel gymViewModel = new GymViewModel
{
ListOfMuscles = GetAllMuscles().ToList()
};
return gymViewModel;
}
}
The MuscleFacade class it's what I inject on my controller with Autofac, I inject an IMuscleFacade in its constructor.
Now the thing is, my MuscleTypeViewModel have a list of MuscleViewModel these models are mapped with their Domain classes counterparts, and in this particular case a MuscleType have many Muscle (Eg: Arm have bicep, tricep, etc) so I put navigational properties on each of them, like so:
public class MuscleType : IEntity
{
public int Id { get; set; }
[StringLength(100)]
public string MuscleTypeName { get; set; }
public ICollection<Muscle> Muscles { get; set; }
}
public class Muscle : IEntity
{
public int Id { get; set; }
[StringLength(100)]
public string MuscleName { get; set; }
public int MuscleTypeId { get; set; }
public MuscleType MuscleType { get; set; }
}
Now let's look at GetAllMuscles method in the Facade again:
public IEnumerable<MuscleViewModel> GetAllMuscles()
{
var source = _unitOfWork.MuscleRepository
.Get()
.ToList();
var result = source.Select(x => _muscleMapping.MuscleToModel(x));
return result;
}
What if I want to Eager-Load MuscleType, how can I change the Get() in order to receive and Expression of Func instead of a string?
You can define a helper class that contains your include definitions:
abstract class IncludeDefinition<TEntity>
{
public abstract IQueryable<TEntity> Include(IQueryable<TEntity> entities);
}
class IncludeDefinition<TEntity, TProperty> : IncludeDefinition<TEntity>
{
public IncludeDefinition(Expression<Func<TEntity, TProperty>> includeEx)
{
_includeEx = includeEx;
}
private readonly Expression<Func<TEntity, TProperty>> _includeEx;
public override IQueryable<TEntity> Include(IQueryable<TEntity> entities)
{
return entities.Include(_includeEx);
}
}
Then use the IncludeDefinition in your Get method
public IEnumerable<Muscle> Get(params IncludeDefinition<Muscle>[] includes)
{
IQueryable<Muscle> muscles = ...;
foreach (var item in includes)
{
muscles = item.Include(muscles);
}
return muscles.ToList();
}
And call the method
_unitOfWork.MuscleRepository
.Get(new IncludeDefinition<Muscle, MuscleType>(m => m.MuscleType));
// Include as many as you wish
_unitOfWork.MuscleRepository
.Get(new IncludeDefinition<Muscle, MuscleType>(m => m.MuscleType),
new IncludeDefinition<Muscle, SomeOtherRelatedEntity>(m => m.SomeOtherProperty));
Edit here comes some way to "just include" instead of writing complicated syntax.
Create a new interface IQueryRepository that supports Get without explicit includes and Include, derive IGenericRepository from this interface:
public interface IQueryRepository<TEntity>
where TEntity : class
{
IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null);
IQueryRepository<TEntity> Include<TProperty>(Expression<Func<TEntity, TProperty>> referenceExpression);
}
public interface IGenericRepository<TEntity> : IQueryRepository<TEntity>
where TEntity : class
{
IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
params IncludeDefinition<TEntity>[] include);
// other methods like GetByID, Add, Update...
}
Update the GenericRepository definition - it uses the approach with IncludeDefinition that I initially described and it returns a GenericQueryRepositoryHelper when Include is called.
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
internal DbSet<TEntity> dbSet;
public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null)
{
return Get(filter, orderBy, new IncludeDefinition<TEntity>[0]);
}
public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, params IncludeDefinition<TEntity>[] includes)
{
IQueryable<TEntity> query = dbSet;
foreach (var item in includes)
{
query = item.Include(query);
}
if (filter != null)
{
query = query.Where(filter);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public IQueryRepository<TEntity> Include<TProperty>(Expression<Func<TEntity, TProperty>> referenceExpression)
{
return new GenericQueryRepositoryHelper<TEntity>(this, new IncludeDefinition<TEntity, TProperty>(referenceExpression));
}
// other methods like GetByID, Add, Update...
}
Implement the GenericQueryRepositoryHelper to store includes and apply them when Get is called
public class GenericQueryRepositoryHelper<TEntity> : IQueryRepository<TEntity>
where TEntity : class
{
private readonly IList<IncludeDefinition<TEntity>> _includeDefinitions;
private readonly IGenericRepository<TEntity> _repository;
internal GenericQueryRepositoryHelper(IGenericRepository<TEntity> repository, IncludeDefinition<TEntity> includeDefinition)
{
_repository = repository;
_includeDefinitions = new List<IncludeDefinition<TEntity>> { includeDefinition };
}
public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null)
{
return _repository.Get(filter, orderBy, _includeDefinitions.ToArray());
}
public IQueryRepository<TEntity> Include<TProperty>(Expression<Func<TEntity, TProperty>> referenceExpression)
{
_includeDefinitions.Add(new IncludeDefinition<TEntity, TProperty>(referenceExpression));
return this;
}
}
Happy querying with includes:
var repo = new GenericRepository<Muscle>(...);
repo.Include(x => x.MuscleType)
.Include(x => x.MuscleType.Muscles)
.Get(x => x.MuscleName == "Test", x => x.OrderBy(m => m.MuscleName));
I want to be able to use a generic service class of type T that will allow me to query the database dynamically. For example. Normally i would do something like this to delete a record
public void Delete(Post post)
{
this._context.Posts.Remove(post);
}
I want to be able to do this
public void Delete(T post)
{
this._context<T>.Remove(post);
}
I found an article here that sort of brushes over it, but if doesnt seem like a clean way to implement it. https://blog.magnusmontin.net/2013/05/30/generic-dal-using-entity-framework/
You need DbContext.Set
https://msdn.microsoft.com/en-us/library/gg679544(v=vs.113).aspx
Returns a non-generic DbSet instance for access to entities of the given type in the context and the underlying store
public void Delete<T>(T post)
where T : class
{
this._context.Set<T>.Remove(post);
}
For later on, you can also query based on:
this._context.Set<T>.AsQueryable().Where(predicate);
In this instance predicate would be a Expression<Func<T, bool>>
So you can have a generic query method:
public IEnumerable<T> Query<T>(Expression<Func<T, bool>> predicate)
where T : class
{
return this._context.Set<T>().AsQueryable().Where(predicate).ToList();
}
... but I'm digressing from the question slightly now!
You can use Generic repository pattern
public class Repository<TEntity> where TEntity : class
{
private dynamic _context;
private DbSet<TEntity> _dbSet;
protected DbContext Context
{
get
{
if (_context == null)
{
_context = DataContextFactory.GetDataContext();
}
return _context;
}
}
protected DbSet<TEntity> DBSet
{
get
{
if (_dbSet == null)
{
_dbSet = this.Context.Set<TEntity>();
}
return _dbSet;
}
}
public virtual IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
{
return this.GetQuery(predicate, orderExpression).AsEnumerable();
}
public virtual IQueryable<TEntity> GetQuery(Expression<Func<TEntity, bool>> predicate = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderExpression = null)
{
IQueryable<TEntity> qry = this.DBSet;
if (predicate != null)
qry = qry.Where(predicate);
if (orderExpression != null)
return orderExpression(qry);
return qry;
}
public virtual void Insert<T>(T entity) where T : class
{
DbSet<T> dbSet = this.Context.Set<T>();
dbSet.Add(entity);
}
public virtual void Insert(TEntity entity)
{
this.DBSet.Add(entity);
}
public virtual void Update<T>(T entity) where T : class
{
DbSet<T> dbSet = this.Context.Set<T>();
dbSet.Attach(entity);
this.Context.Entry(entity).State = EntityState.Modified;
}
public virtual void Update(TEntity entity)
{
this.Attach(entity);
this.Context.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete<T>(T entity) where T : class
{
DbSet<T> dbSet = this.Context.Set<T>();
if (this.Context.Entry(entity).State == EntityState.Detached)
dbSet.Attach(entity);
dbSet.Remove(entity);
}
public virtual void Delete(TEntity entity)
{
if (this.Context.Entry(entity).State == EntityState.Detached)
this.Attach(entity);
this.DBSet.Remove(entity);
}
public virtual void Delete<T>(object[] id) where T : class
{
DbSet<T> dbSet = this.Context.Set<T>();
T entity = dbSet.Find(id);
dbSet.Attach(entity);
dbSet.Remove(entity);
}
public virtual void Delete(object id)
{
TEntity entity = this.DBSet.Find(id);
this.Delete(entity);
}
public virtual void Attach(TEntity entity)
{
if (this.Context.Entry(entity).State == EntityState.Detached)
this.DBSet.Attach(entity);
}
public virtual void SaveChanges()
{
this.Context.SaveChanges();
}
}
Usage:
public class Sample
{
public void AddNewPerson(Person newPerson)
{
var personRepo = new Repository<Person>();
personRepo.Insert(newPerson);
personRepo.SaveChanges();
}
public void DeletePerson(int personId)
{
var personRepo = new Repository<Person>();
Person person= personRepo.Find(p => p.Id == personId).SingleOrDefault();
personRepo.Delete(person);
}
}
I want to write a one class generic for all Repository
I have a class Entity (Product,price,.... )
and the Interface IRepository
public interface IRepository<T>
{
Dictionary<int, T> myProduct { get; set; }
IEnumerable<T> List { get; }
void Add(T entity);
void Delete(T entity,int key);
void Update(T entity,int key);
T FindById(int Id);
}
I can write my Repository for each business object like ProudductRepository, priceReporsitory,.....
but I need to implements as a generic something like this
public class Repository<E, C> : IRepository<E>
and I use this for all my business object not one foreach entity
You can do that as shown below.This is just an example.
Create a Generic Repository
namespace ContosoUniversity.DAL
{
public class GenericRepository<TEntity> where TEntity : class
{
internal SchoolContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(SchoolContext 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,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Delete(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);
}
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
}
Please read more about it on Implement a Generic Repository and a Unit of Work Class article.
More Articles for you :
Generic Repository and UnitofWork patterns in MVC
Generic Repository and Unit of Work Pattern
I currently have this class make up for my Generic Repository
public abstract class RepositoryBase<T> where T : class
{
private readonly ISession session;
public RepositoryBase(ISession session)
{
this.session = session;
this.session.FlushMode = FlushMode.Auto;
}
public void Start()
{
this.session.BeginTransaction();
}
public bool Add(T entity)
{
this.session.Save(entity);
return true;
}
public bool AddAll(IEnumerable<T> items)
{
foreach (T item in items)
{
this.session.Save(item);
}
return true;
}
public bool Update(T entity)
{
this.session.Flush();
this.session.Update(entity);
return true;
}
public bool Delete(T entity)
{
this.session.Delete(entity);
return true;
}
public bool DeleteAll(IEnumerable<T> entities)
{
foreach (T entity in entities)
{
this.Delete(entity);
}
return true;
}
public T GetById(int id)
{
return this.session.Get<T>(id);
}
public T GetById(string id)
{
return this.session.Get<T>(id);
}
public T GetById(long id)
{
return this.session.Get<T>(id);
}
public T GetById(Guid id)
{
return this.session.Get<T>(id);
}
public IQueryable<T> GetAll()
{
return this.session.Query<T>();
}
public T Get(Expression<System.Func<T, bool>> expression)
{
return GetMany(expression).SingleOrDefault();
}
public IQueryable<T> GetMany(Expression<System.Func<T, bool>> expression)
{
return GetAll().Where(expression).AsQueryable();
}
}
When I call the GetById method which takes a string parameter I am met with an exception error that states GetById is expecting type Guid not string. How do I design this method to accept a string parameter?
You can design your class adding another generic parameter for the type of id:
public abstract class Repository<T, TId>
{
public T Get(TId id)
{
}
}
take a look at this https://github.com/sharparchitecture/sharp-architecture/wiki