0

I have an interface IMstTuver which is implemented by the MstTuver class. IMstTuver contains MaxVersion and Agenttype parameters.

public class GetTable<T> where T : IMstTuver
{
    public IMstTuver GetEntities(DbContext context, string agenttype) 
    {
        long maxVersion = context.Set<T>().Max(x => x.MaxVersion);
        IMstTuver mstTuver = context.Set<T>()
                                    .Where(x => x.MaxVersion == maxVersion && 
                                                x.AgentType == agenttype)
                                    .FirstOrDefault();
        return mstTuver;
    }
}

In my class:

table.GetEntities(MyDbContext, "MSMA") as MstTuver;

I am getting an error

The type 'T' must be a reference type in order to use it as parameter 'TEntity' in the generic type or method 'System.Data.Entity.DbSet'

Please help.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ankita
  • 29
  • 4

3 Answers3

4

Set<T> has a generic constraint that T must be a reference type, which means that your class needs to have one too. The fix is to apply the following modification to all generic classes and/or methods up the call chain:

public class GetTable<T> where T : class, IMstTuver
Kirill Shlenskiy
  • 9,367
  • 27
  • 39
1

You can declare T as a reference type by adding the class type-constraint to your method:

public class GetTable<T> where T : class, IMstTuver
{
    //...
spender
  • 117,338
  • 33
  • 229
  • 351
0

I have done something like this in the past and found it easier to put the generic and constraint on the methods than the type. This will allow the same repository type to serve multiple entity types (as long as they meet the constraints).

Example:

public class GetTable
{
    public T GetEntities<T>(DbContext context, string agenttype)where T : class, IMstTuver
    {
        long maxVersion = context.Set<T>().Max(x => x.MaxVersion);
        IMstTuver mstTuver = context.Set<T>().Where(x => x.MaxVersion == maxVersion && x.AgentType == agenttype).FirstOrDefault();
        return mstTuver;
    }
}

In the future when you are returning a generic as a generic from an existing library you can check the constraints on the method you are calling and implement those same constraints. In this case the Set<T> method is constrained to class. You can then add additional non conflicting constraints as you see fit.

DbContext.Set Method

public virtual DbSet<TEntity> Set<TEntity>() where TEntity : class
Igor
  • 60,821
  • 10
  • 100
  • 175