6

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/

2
  • 2
    Just use _context.Set<T>().Remove(post) Commented Apr 28, 2017 at 10:28
  • In the net you can find many articles regarding generic repository implementation with EF such as this or this Commented Apr 28, 2017 at 10:44

2 Answers 2

6

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!

Sign up to request clarification or add additional context in comments.

2 Comments

Tried this, but i get an error. The type 'T' must be a reference type in order to use it as parameter 'TEntity' in the generic type or method 'DbContext.Set<TEntity>()'
ah- see my update for Query - you need the where clause
1

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);
    }
}

1 Comment

Will this work if Person has hierarchy of child objects like List<Address>?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.