1

I have a number of tables in my SQL DB that store basic KVP data. they all have the pattern of Id(int), Description(varchar(..)).

I require them all at one stage or another in my MVC application and i am trying to create an anonymous method that will take the type of entity class and return a list of that items data. I would like to be able to use this method for any number of tables in my database without having to extend the methods i am writing by too much.

Example Data:

  • Id: 1, Description: Red
  • Id: 2, Description: Blue
  • Id: 3, Description: Green

ISet Implementation:

public interface ISet
{
    int Id { get; set; }
    string Description { get; set; }
}

Possible Method Implementation

public static IList<T> BuildSet<T>()
{
    using (var db = new somethingEntities())
        return db.Set(typeof(T)).Cast<ISet>().Select(c => new { c.Id, c.Description }).ToList();
}

Usage

var data = BuildSet<YourType>();

Runtime Error

Cannot create a DbSet<ISet> from a non-generic DbSet for objects of type 'YourType'.

Does anyone know how to do this?

Thanks.

Grant
  • 11,138
  • 32
  • 94
  • 140

2 Answers2

0

Problem solved.

Method Declaration

public static List<ISet> BuildSet<T>() where T : class
{
    using (var db = new somethingEntities())
        return db.Set<T>().ToList().Cast<ISet>().ToList();
}

Usage

var data = ...BuildSet<YourType>();
Grant
  • 11,138
  • 32
  • 94
  • 140
  • System.InvalidCastException: 'Unable to cast object of type 'System.Data.Entity.DynamicProxies.Set_33C84C30E063218CBB4881E395838375014F3EFBA09108F25ACF2FB2FCA1E92D' to type 'CustomTypes.ISet'.' – Ivan Silkin Oct 14 '21 at 00:28
0

I assume that the DbSet's are small as ToList() will fetch all the results in one go?

However, here's a simpler version of your code (you specify the interface ISet in the generic type constraint):

public static IList<ISet> BuildSet<T>() 
    where T : class, ISet
{
    using (var db = new somethingEntities())
        return db.Set<T>().ToList();
}

There's also the option of an extension method for your DbContext:

public IEnumerable<ISet> BuildSet<T>(this DbContext context)
    where T : class, ISet
{
    return context.Set<T>().AsEnumerable();
}

which you can then use within the lifetime of your context, possible for a more efficient operation. (I know I'm assuming too much but I feel it's useful information anyway.)

public void SomeOperation()
{
    using (var db = new somethingEntities())
    {
        foreach (var item in db.BuildSet<SimpleSet>())
        {
            //do something with item
            //SaveChanges() every 100 rows or whatever
        }
    }
}
qujck
  • 14,388
  • 4
  • 45
  • 74