I have a database mapped with Entity Framework,
I need to implement a generic method for getting a a list of items based on a parameter that I pass:
getGenericList("product"); // returns the list of products
getGenericList("customer"); // returns the list of customers
I need to dynamically get the dbSet
. My method is implemented like this:
public static List<object> getGenericList(string entityType)
{
List<object> myDynamicList = new List<object>();
using (cduContext db = new cduContext())
{
DbSet dbSet = db.getDBSet(entityType);
var myDynamicList = dbSet.Select(p => p).ToList();
}
return new List<object>();
}
my dbSets
are auto-generated by EF code first :
public DbSet<Product> Products { get; set; }
public DbSet<Custommer> Custommers { get; set; }
my getDBSet(entityType)
method is implemented in the context, like this:
public DbSet<T> getDBSet<T>(string entityName) where T : class
{
switch (entityName)
{
case "product":
return Products;
case "custommer":
return Custommers;
I then got this error:
Cannot implicitly convert type 'System.Data.Entity.DbSet' to 'System.Data.Entity.DbSet'
Any Idea please !?
N.B. , the method Set()
of the dbContext
is not OK; the type should be explicitly given ...
It's better to stay away from strings as types and mapping them to real types; that's a code smell. Instead, use the types themselves. Either way, let's refactor your code that uses the getGenericList()
method to use generics. If you can't get away from strings, do the mapping in the code that calls getGenericList()
as opposed to mapping inside that method, since we're following the pattern you've set forth.
Also note that in your original getGenericList()
you're always returning an empty list, as opposed to the list you obtained via EF. You're also using 2 different myDynamicList
variables; the outer one is masked by the one in the scope of the using
statement which is why you don't get a compiler error. Once the using
goes out of scope, the inner myDynamicList
goes out of scope too. I've addressed that here.
public static List<T> getGenericList<T>()
{
List<T> myDynamicList;
using (cduContext db = new cduContext())
{
// consider using exception handling here as GetDbSet might get an invalid type
DbSet dbSet = db.GetDbSet<T>();
myDynamicList = dbSet.Select(p => p).ToList();
}
if (myDynamicList != null && myDynamicList.Count() > 0)
{
return myDynamicList;
}
return new List<T>();
}
// in your context class
public DbSet<T> GetDbSet<T>() where T : class
{
return this.Set<T>();
}
// this is the code that calls getGenericList(); put this inside a function somewhere.
// entityName holds a string value, set previously
switch(entityName.ToLower()) // making entityName case insensitive
{
case "product":
return getGenericList<Product>();
case "customer":
return getGenericList<Customer>();
}
Hopefully you won't have too many entity types that you want to map, or you'll end up with a huge switch
statement. Again, if you're using a switch
statement, in general it's probably an indication that you need to re-think your approach.