How to implement a Person repository function for the Generic repository - Asp.net MVC and EF Core

1

I have a function to return the highest value of an ID field from a table using EF Core. But I'd like to implement it in my generic repository to be dynamic and to be used by all classes. How do I do this?

//Funcionar no Repositório de Pessoa
public int GetMax()
{
  return DbSet.Select(p=> p.Id).DefaultIfEmpty(0).Max();
}

//Repositório Genérico
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    protected readonly RetaguardaContext Db;
    protected readonly DbSet<TEntity> DbSet;

    public Repository(RetaguardaContext context)
    {
        Db = context;
        DbSet = Db.Set<TEntity>();
    }

    public virtual void Add(TEntity obj)
    {
        DbSet.Add(obj);
    }

    public virtual TEntity GetById(int id)
    {
        return DbSet.Find(id);
    }

    public virtual IQueryable<TEntity> GetAll()
    {
        return DbSet;
    }

    public virtual void Update(TEntity obj)
    {
        DbSet.Update(obj);
    }

    public virtual void Remove(int id)
    {
        DbSet.Remove(DbSet.Find(id));
    }

    public int SaveChanges()
    {
        return Db.SaveChanges();
    }

    public void Dispose()
    {
        Db.Dispose();
        GC.SuppressFinalize(this);
    }

    public void Remove(params object[] keyValues)
    {
        DbSet.Remove(DbSet.Find(keyValues));
    }

    public TEntity GetByIds(params object[] keyValues)
    {
        return DbSet.Find(keyValues);
    }       
}
    
asked by anonymous 18.08.2018 / 13:23

1 answer

1

You will need to create a Expression<Func<TEntity, int>> so that your expression works by choosing the desired field, eg

In your class of Interface create a method:

int GetMax(Expression<Func<TEntity, int>> select);

then implements in your concrete class:

public int GetMax(Expression<Func<TEntity, int>> select)
{
    return DbSet.Select(select).Max();
}

This example works fine with the maximum value contained in some field of your table, but, the expression for Select has 4 overloads ( overloads ) that can be implemented, but the one that is in the answer refers to your question.

In use you need to identify the field that needs to retrieve the maximum value:

Sample template:

public class Cliente 
{
    public int Codigo { get; set; }
    public string Nome { get; set; }
}

Code:

Repository<Cliente> rep = new Repository<Cliente>(new RetaguardaContext());
var maximo = rep.GetMax(x => x.Codigo)

The code above is good code because it also prevents typing of fields other than int , but if you want to leave the code more generic another method can be created in Interface

T GetMax<T>(Expression<Func<TEntity, T>> select);

and implement as follows:

public T GetMax<T>(Expression<Func<TEntity, T>> select)
{
    return DbSet.Select(select).Max();
}

and use the same as the other:

var maximo = c.GetMax(x => x.Codigo);

The functionality increases to other data types ( int , long , etc);

18.08.2018 / 14:25