11


What I'm trying to do is to pass an entity object to method and return all the names of the properties in it.
I'm using this code to get all the props names :

return classObject.GetType().GetProperties();

The problem is that this code return "EntityKey" and "EntityState" as properties whe I use it with Entity Object.
Is there any way to do it ?

Thanx in advance

Dabbas
  • 3,112
  • 7
  • 42
  • 75

4 Answers4

23

You want all direct properties, but not the properties of the base type, which in your case is EntityObject:

var type = classObject.GetType();
//alternatively call out directly: typeof(EntityObject).GetProperties()...
var basePropertyNames = type.BaseType.GetProperties().Select(x => x.Name);
var props = type.GetProperties().Where(p => !basePropertyNames.Contains(p.Name));

This sample assumes there is a base type (which is the case for DB first), refactor when that is not guaranteed.

Edit from @Matt's comment: All of the above is unnecessary, could slap my head for not thinking of this - just use the right binding flags:

return classObject.GetType().GetProperties(BindingFlags.DeclaredOnly | 
                                           BindingFlags.Public | 
                                           BindingFlags.Instance);
BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
  • 6
    Why not use `classObject.GetType().GetProperties(BindingFlags.DeclaredOnly)`? – Matt Greer May 01 '11 at 21:01
  • 5
    @Matt: Because I'm an id*ot -fixing my answer – BrokenGlass May 01 '11 at 21:05
  • 2
    and @Matt: thanks for the answers. @BrokenGlass: when I used @Marrs's modified code I get the properties but also I get some properties I don't want which is the Navigation properties so I modified the code little bit and it worked for now: 'var basePropertyNames = classObject.GetType().BaseType.GetProperties().Select(x => x.Name); return classObject.GetType().GetProperties().Where(p => !basePropertyNames.Contains(p.Name) && !p.PropertyType.IsClass).Select(x => x.Name);' I don't know if this will work for all the Entities or not .. – Dabbas May 01 '11 at 21:27
  • 1
    @Aione: you can just add that to the GetProperties call above instead: `GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance).Where(p => !p.PropertyType.IsClass)` – BrokenGlass May 01 '11 at 21:31
  • Thanks for this answer and discussion in this answer, it's really help me alot – Sruit A.Suk May 22 '16 at 02:46
8

It is also possible without reflection:

using (var context = new ModelContainer())
{
    // Access CSDL
    var container = context.MetadataWorkspace
                           .GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
    // Access name of related set exposed on your context
    var set = container.BaseEntitySets[context.YourEntitySet.EntitySet.Name];
    // Access all properties
    var properties = set.ElementType.Members.Select(m => m.Name).ToList();
    // Access only keys
    var keys = set.ElementType.KeyMembers.Select(m => m.Name).ToList();
}

As you can see you have access to much more then names. The example shows that you can now which property is part of key. If you access Members directly you can know which property is scalar, complex type or navigation property.

All information are already loaded so there is no need for reflection. If you want to use reflection don't forget to use it only once (first time you need it) and then store and reuse received property names. Reflection is slow so using it each time you need names is a bad practice.

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
2

I had the same problem. The solution I found was to create an array with the name of the properties to return (I olnly need a few). In your case, since it can be laborious to keep track of all properties, I would filter the properties EntityKey and EntityState and return all the others. The code would be something like this:

public IEnumerable<PropertyInfo> GetProperties()
{
    Type t = this.GetType();

    return t.GetProperties()
        .Where(p => (p.Name != "EntityKey" && p.Name != "EntityState"))
        .Select(p => p).ToList();
}

Don't know if there is a better solution, but it would be nice ;) Hope it helps!

jmpcm
  • 1,814
  • 2
  • 19
  • 27
1

As stated by BrokenGlass but beware if you need performance and you want to do this in loops. Reflection is not a fast thing.

If you need performance you may wish to put a virtual method in your base class to retrieve the properties as an array of strings or whatever, and override that in all derived classes. This would be the fastes approach but with more coding.

Marino Šimić
  • 7,318
  • 1
  • 31
  • 61