Reputation: 33
Some of my Entity Framework classes implement a certain interface, say IHasYearColumn
, which means the table has a year
column (int
).
I would like to iterate over all of the tables with year columns and do some work.
I managed to get the relevant types using:
var typesWithYear = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a=>a.GetTypes())
.Where(t=>typeof(IHasYearColumn).IsAssignableFrom(t);
I verified this works, and indeed I get all the types I want.
Now, I would like to iterate over the respective table get the year values from all the records:
foreach (t in typesWithYear)
myDbEntites.Set<t>().Select(x=>x.Year);
This obviously won't compile since t
is not recognized as IHasYearColumn
. So, I tried casting all types in typesWithYear into IHasYearColumn
but this would not help. I got an InvalidCastException
.
Any ideas will be most welcomed.
Edit Found the answer here.
Upvotes: 1
Views: 1248
Reputation: 4280
Here is a solution that worked for me. IHaveSpecificIdNo
is my analog to the initial questions IHasYearColumn
var currentSpecificId = "123";
var DataContext = this;
var setProps = DataContext
.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(x =>
{
return x.PropertyType.IsGenericType
//todo better check
&& x.PropertyType.Name.StartsWith("DbSet");
})
.ToArray();
foreach (var setProperty in setProps)
{
var entityType = setProperty.PropertyType.GetGenericArguments().First();
var set = DataContext.Set(entityType);
if (typeof (IHaveSpecificIdNo).IsAssignableFrom(entityType))
{
var items = ((IQueryable<IHaveSpecificIdNo>)set)
.Where(x => x.SpecificIdNo == currentSpecificId).ToArray();
if(items.Length == 0)
{
continue;
}
//do something
}
}
Upvotes: 1
Reputation: 1387
This might work:
foreach (t in typesWithYear)
myDbEntites.Set(t).AsQueryable().Cast<IHasYearColumn>().Select(x=>x.Year);
Upvotes: 0
Reputation:
First of all, your code for getting types include interface itself, so you need to add additional predicate:
var typesWithYear = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(a=>a.GetTypes())
.Where(t=>typeof(IHasYearColumn)
.IsAssignableFrom(t))
.Where(t => t.IsClass && !t.IsAbstract);
Next, use non-generic method for getting dbSet:
foreach (var type in typesWithYear)
{
var set = myDbEntites.Set(type);
}
What's more, I'm not sure that EF will manage cast to an interface in order to produce SQL. If no (you can try it like GDS proposed), you can use Dynamic LINQ:
foreach (var type in typesWithYear)
{
var set = myDbEntites.Set(type);
yield return ((IQueryable)set).Select("Year")
.Cast<int>(); // or sth else, your choice
}
EF supports casting to entity models or primitive type for sure.
Upvotes: 0