2

I am working on a project.It's following "Unit of work" pattern.I want to write a Dynamic method where I will pass the table name it will return the max value of primary key column or I will pass the table and column name it will return the max value of that column. It will look something like this--

public int GetMaxPK<T>()
{
    GetMaxId= ??
    return GetMaxId;
}

Is it possible? How can I do this? Or any suggestion?

Salah Akbari
  • 39,330
  • 10
  • 79
  • 109
Mohammad Sadiqur Rahman
  • 5,379
  • 7
  • 31
  • 45
  • you could use the `where` constraint and specify an Interface or BaseType supporting such value: `public int GetMaxPK() where T is BaseType` – LuckyLikey Sep 13 '17 at 09:31

3 Answers3

3

You can define an interface with one properties:

public interface IMax
{
    int Id { get; set; }
}

And then your generic class should implement this interface:

public class yourClass<T> where T : class , IMax

Finally:

public int GetMaxPK()
{
    GetMaxId= yourTable.Max(c => c.Id);
    return GetMaxId;
}

Your complete code should be something like this:

public class yourClass<T>  where T : class, IMax
{
    public int GetMaxPK(IEnumerable<T> yourTable)
    {
        var GetMaxId = yourTable.Max(c => c.Id);
        return GetMaxId;
    }
}
Salah Akbari
  • 39,330
  • 10
  • 79
  • 109
  • i am using different name(as primary key column) for different table not using as "id".So i have to pass column name either or pick primary key column whatever name it has. – Mohammad Sadiqur Rahman Sep 13 '17 at 09:44
  • @MohammadSadiqurRahman When you are using the generic you should try to have more common logic as you can. So I'd suggest to rename your PK to ids or something that is same in all of your tables.. – Salah Akbari Sep 13 '17 at 09:51
  • can i make my column name dynamic also? – Mohammad Sadiqur Rahman Sep 13 '17 at 09:56
  • @MohammadSadiqurRahman You can use `System.Linq.Dynamic` as I answered in this question https://stackoverflow.com/a/44143131/2946329 However I still recommend to rename your PKs to something that is same in all of your tables which make your code more readable and reusable. – Salah Akbari Sep 13 '17 at 09:59
  • @MohammadSadiqurRahman You can also use reflection, which is very expensive in general terms and it doesn't recommended for this scenarios. – Salah Akbari Sep 13 '17 at 10:04
3

In my Project,I wrote in mvc controller to get maxId like this--

public class PurchaseOrderController : Controller
{    
   private IPurchaseOrder interfaceRepository;

    public PurchaseOrderController()
    {
        if (interfaceRepository==null)
        {
            this.interfaceRepository= new Repository();
        }
    }
    int maxId=interfaceRepository.GetMaxPK(a=>a.POMSTID);
}

here

a=>a.POMSTID

is the colum selector that you want to query.Suppose you want to select column named "PODETID" then column selector will be like this--

a=>a.PODETID

now in interface --

    public interface IPurchaseOrder:IRepository<PURCHASEORDERMASTER>
    {

    }

Here "PURCHASEORDERMASTER" is my query table or TEntity.

public interface IRepository<TEntity> where TEntity : class
{
    int GetMaxPK(Func<TEntity, decimal> columnSelector);
}

now in the repository(or concrete) class(that inherit the interface) where you call the db you have to write like this--

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
 {   

    public int GetMaxPK(Func<TEntity, decimal> columnSelector)
    {
        var GetMaxId = db.Set<TEntity>().Max(columnSelector);
        return GetMaxId;
    }
 }

here db is the database context and decimal is the data type of my query column.

anis programmer
  • 989
  • 1
  • 10
  • 25
  • Excellent.your answer solved my problem.A lot of days i am trying to get maxID dynamically but could not find the solution.According to your answer it gives me maxID perfectly.thanks for your answer. – Mohammad Sadiqur Rahman Sep 14 '17 at 11:21
2

You could consider using something similar to the Max extension method

TResult Max<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector);

Which when adapted to your scenario

public int GetMaxPK<TTable>(IEnumerable<TTable> table, Func<TTable, int> columnSelector) {
    var maxId= table.Max(columnSelector);
    return maxId;
}

Or assuming the source is already internal to the encapsulating class for example something like DbContext

DbContext db;

//...

public int GetMaxPK<TTable>(Func<TTable, int> columnSelector) {
    var maxId = db.Set<TTable>().Max(columnSelector);
    return maxId;
}

And called like

var maxId = myClass.GetMaxPK<TableName>(t => t.PKColumnName);
Nkosi
  • 235,767
  • 35
  • 427
  • 472