Reputation: 140
Purpose: I need to get the name of the dbset name of the entity typeof(UserAccount) = "UserAccounts". But in runtime I need a common type for the loop and therefor do not know example "UserAccount". Only the "name" from typeof?
I have created an DbContext with some entities. I have been googling for some time but it do not seem to be working for me because of the Type converting?
Please see my method GetDbSetName in the bottom of this description.
I am pretty new at this EF stuff - so please help med with my issue as described below ;-)
public class MyEntities : DbContext
{
public DbSet<UserAccount> UserAccounts { get; set;}
public DbSet<UserRole> UserRoles { get; set; }
public DbSet<UserAccountRole> UserAccountRoles { get; set; }
}
Defined a list of Type to control the output:
public static List<Type> ModelListSorted()
{
List<Type> modelListSorted = new List<Type>();
modelListSorted.Add(typeof(UserRole));
modelListSorted.Add(typeof(UserAccountRole));
modelListSorted.Add(typeof(UserAccount));
return modelListSorted;
}
The problem is below using Type - If I use "UserAccount" it Works and I get "UserAccounts". But I do not have the "UserAccount" in runtime as I am in a loop with a serie of types. I do only have the Type list giving the e
public static loopList()
{
List<Type> modelListSorted = ModelListSorted();
foreach (Type currentType in modelListSorted)
{
string s = DataHelper.GetDbSetName(currentType, db);
}
}
HERE IS THE METHOD GIVING ME THE CHALLANGES ;-) Meaning not compiling. saying I am missing a assembly? I know it is pretty pseudo but can this be done smoothly?
public static string GetDbSetName(Type parmType, MyEntities db)
{
string dbsetname = (db as IObjectContextAdapter).ObjectContext.CreateObjectSet<parmType>().EntitySet.Name;
return dbsetname;
}
Upvotes: 4
Views: 3290
Reputation: 109079
The challenge here is that two reflection steps are involved, one to invoke the generic CreateObjectSet
method and one to get the EntitySet
from the result. Here's a way to do this:
First, the method:
string GetObjectSetName(ObjectContext oc, MethodInfo createObjectSetMethodInfo,
Type objectSetType, Type entityType)
{
var objectSet = createObjectSetMethodInfo.MakeGenericMethod(entityType)
.Invoke(oc, null);
var pi = objectSetType.MakeGenericType(entityType).GetProperty("EntitySet");
var entitySet = pi.GetValue(objectSet) as EntitySet;
return entitySet.Name;
}
As you see, I first get the ObjectSet
by invoking the MethodInfo
representing the generic method CreateObjectSet<T>()
. Then I find the PropertyInfo
for the EntitySet
property of the generic type ObectSet<T>
. Finally, I get this property's value and the name of the obtained EntitySet
.
To do this, I first get a MethodInfo
for CreateObjectSet<>()
(the one without parameters) and the ObjectSet<>
type
var createObjectSetMethodInfo =
typeof(ObjectContext).GetMethods()
.Single(i => i.Name == "CreateObjectSet"
&& !i.GetParameters().Any());
var objectSetType = Assembly.GetAssembly(typeof(ObjectContext))
.GetTypes()
.Single(t => t.Name == "ObjectSet`1");
In GetObjectSetName
their generic parameters are specified by a concrete entity type, which is done by these "MakeGeneric..." methods.
var oc = (dbContextInstance as IObjectContextAdapter).ObjectContext;
var entityType = typeof(UserRole);
var name = GetObjectSetName(oc, createObjectSetMethodInfo, objectSetType, entityType);
In EF 6 these should be the using
s:
using System.Data.Entity.Core.Metadata.Edm
using System.Data.Entity.Core.Objects
using System.Data.Entity.Infrastructure
using System.Linq
using System.Reflection
Upvotes: 3