2

How can I get a list of entity types that are part of the model, so I can test that the model actually works with that entity type?

var dcx = new MyDbContext();
var lst = new List<Type>();
//populate the list here somehow
//...
foreach (var t in lst) {
    var set = dcx.Set(t); //I'm trying to avoid an exception here
    try {
        var test = set.FirstOrDefault();
    } catch (Exception ex) {
        Console.WriteLine("{0} has an error", t);
    }
}

NB: It is perfectly possible to query dcx.Set(t) even if there is no corresponding DbSet property on MyDbContext; therefore it's not enough to iterate via reflection over the properties of MyDbContext whose return type's generic definition is DbSet<T> or even IDbSet<T>.

Zev Spitz
  • 13,950
  • 6
  • 64
  • 136
  • The models or POCOs will be different types, you cannot create a List of different types, you can only create a List of the same type, in this case a List of a specific POCO or model type. The only option is List n = new List(); I would not recommend this. – Julius Depulla Nov 26 '15 at 00:30
  • @coderealm I'm not sure you are seeing that right. The list is a `List` of `Type`, and the operator loops through each `Type` and gets the cooresponding `Set` from the database context. I'm not sure you can avoid an exception here, although if you move the `set = dcx.Set(t)` to inside the try/catch (or put it in its own try/catch) then you can at least swallow it. Otherwise you can create an attribute that you put on your model classes that you can query via reflection to get all types with that attribute. – Ron Beyer Nov 26 '15 at 01:37
  • @coderealm I can create a `List` that holds different strings. `System.Type` is simply a class that contains information about a given type. – Zev Spitz Nov 26 '15 at 06:17
  • You may want to look at this: http://stackoverflow.com/a/3893502/861716 – Gert Arnold Nov 28 '15 at 22:01

2 Answers2

1

Maybe something like this?

var types = typeof(MyDbContext)
    .GetProperties()
    .Where(prop => prop.PropertyType.IsGenericType)
    .Where(prop => prop.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>))
    .Select(prop => prop.PropertyType.GenericTypeArguments.First())
    .Distinct();
missemisa
  • 2,600
  • 1
  • 14
  • 10
  • I know, you can use reflection to achieve just about anything. Personally bad choice except for writing plugins, because if I start to think of reflection, I should be thinking of re-designing the solution. Because, with use of reflection , you are literally saying I do not know what I am expecting at runtime but please create the type for me at runtime. When you are writing you own code base you know every type before runtime. – Julius Depulla Nov 26 '15 at 07:59
  • @coderealm This is actually in a class library which has no knowledge of the defined properties on the classes inheriting from DbContext. – Zev Spitz Nov 26 '15 at 12:51
  • 1) Sorry, in my code i use IDbSet, that's why i forgot to change it. 2) Wasn't sure if the distinct could compare Types? That's why i removed it. 3) Did this help you? Seems like you already kind of knew how to do it :) – missemisa Nov 27 '15 at 15:41
  • RE: 2 -- _A Type object that represents a type is unique; that is, two Type object references refer to the same object if and only if they represent the same type. This allows for comparison of Type objects using reference equality._ ([System.Type](https://msdn.microsoft.com/en-us/library/system.type(v=vs.110).aspx)) – Zev Spitz Nov 28 '15 at 17:07
  • RE: 3 -- See the last line of my question. – Zev Spitz Nov 28 '15 at 17:09
1

Thanks to the link in @GertArnold 's comment, I am now using the following:

var dcx = new MyDbContext();
var objContext = ((IObjectContextAdapter)dcx).ObjectContext;
var types = objContext.MetadataWorkspace.GetItems<EntityType>(DataSpace.OSpace).Select(x => Type.GetType(x.FullName));
foreach (var t in lst) {
...
PeterB
  • 886
  • 10
  • 18
Zev Spitz
  • 13,950
  • 6
  • 64
  • 136