This should work for EF6 but I was testing on EFCore.
I've done something somewhat similar to this when I needed to modify all the DbSets that implement a specific interface.
You have two options for your situation. Since all of your model types don't have a common base type (other than object
), you could refactor those generated classes to extract the common properties to a base class (the Id
, Name
, and Type
properties).
Here I'm assuming your Coffee1
and Coffee2
tables just have the entity type Coffee1
and Coffee2
respectively.
Option 1:
Refactor classes and extract those common properties
public partial class Coffee1 : BaseCoffee {}
public partial class Coffee2 : BaseCoffee {}
public abstract class BaseCoffee
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
then your query would look like this
var dbSets = ctxCoin.GetType().GetProperties()
.Where(p => p.PropertyType.IsAssignableTo(typeof(IQueryable<BaseCoffee>)))
.Select(set => set.GetValue(ctxCoin))
.Cast<IQueryable<BaseCoffee>>();
var coffeeList = new ObservableCollection<GenericCoffeeList>();
foreach (var coffee in dbSets)
{
var query = coffee.Select(c => new GenericCoffeeList { CoffeeCatalogId = c.Id, Name = c.Name, Type = c.Type });
foreach (var c in query)
{
coffeeList.Add(c);
}
}
This option is much more type-safe and less error-prone.
Option 2:
Use reflection on IQueryable<object>
Keep your models the same and use this:
var dbSets = ctxCoin.GetType().GetProperties()
.Where(p => p.PropertyType.IsAssignableTo(typeof(IQueryable<object>)))
.Select(set => set.GetValue(ctxCoin))
.Cast<IQueryable<object>>();
var coffeeList = new ObservableCollection<GenericCoffeeList>();
foreach (var queryableObject in dbSets)
{
var query = queryableObject.Select(GenerateGenericCoffee);
foreach (var c in query)
{
coffeeList.Add(c);
}
}
The GenerateGenericCoffee
helper method
GenericCoffeeList GenerateGenericCoffee(object coffeeObject)
{
var objType = coffeeObject.GetType();
return new GenericCoffeeList
{
CoffeeCatalogId = GetProperty<int>("Id"),
Name = GetProperty<string>("Name"),
Type = GetProperty<string>("Type"),
};
T GetProperty<T>(string name)
{
return (T)objType.GetProperty(name).GetValue(coffeeObject);
}
}
If all of your models contain Id
, Name
, and Type
, you will be fine otherwise you'll need to check those properties exist first before making the GenericCoffeeList
item.