16

Given an EntityType, such as "Contact", how can I derive from it the name of the EntitySet it would belong to, i.e. the pluralization such as "Contacts"?

CodeGrue
  • 5,865
  • 6
  • 44
  • 62

3 Answers3

34

If you already have an attached entity (obviously you don't need the first line, just use your existing entity):

  Contact c = context.Contacts.Where(x => x.blah).FirstOrDefault();
  string setName = c.EntityKey.EntitySetName;

Or if you don't:

 string className = typeof(Contact).Name
 var container =   
    context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
    string setName = (from meta in container.BaseEntitySets
                                          where meta.ElementType.Name == className
                                          select meta.Name).First();
S'pht'Kr
  • 2,809
  • 1
  • 24
  • 43
Nix
  • 57,072
  • 29
  • 149
  • 198
  • Very nice. I needed this to do additional customization of POCO entities, like adding GetById() methods to all of the entity classes. – Samuel Meacham Jun 10 '10 at 17:33
  • Genius, I've been trying to do this for ages, thanks a lot, +1 for a great answer – Starjumper Tech SL Aug 24 '12 at 13:43
  • Note that CSpace queries only work when you have connected to the database, so it won't work in scenarios where you just want to query types directly. – John Kaster Jul 11 '13 at 00:03
  • @Nix, could you tell me why the following code has 'EntityKey' nullreference error? entities.CreateObject(typeof(T).Name).EntityKey.EntitySetName – Lei Yang Sep 06 '13 at 00:26
  • how bout for entity sets extended class. e.g. Person has db.Persons and Student : Person has db.Students. I can't seem to find Students in BaseEntitySets – Milo Cabs Oct 16 '14 at 10:17
6

This extension may be useful

public static class MyExtensions
{
    public static string GetEntitySetName<T>(this ObjectContext context)
    {
        string className = typeof(T).Name;

        var container = context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
        string entitySetName = (from meta in container.BaseEntitySets
                                where meta.ElementType.Name == className
                                select meta.Name).First();

        return entitySetName;
    }
}

And use it like:

db.AttachTo(db.GetEntitySetName<MyEntityType>(), myEntityInstance);
Juan Carlos Puerto
  • 2,632
  • 1
  • 26
  • 22
0

Here is a method that works similar to the accepted answer except that this supports a) proxy types (for example, if you dynamically get the type of an EF6 entity it could be of type "Contact_1A2B3C4D5E" instead of "Contact") and b) inheritance (table-per-type, table-per-hierarchy).

private static string GetEntitySetName(ObjectContext objectContext, Type type)
{
    if (objectContext == null) throw new ArgumentNullException(nameof(objectContext));
    if (type == null) throw new ArgumentNullException(nameof(type));

    EntityContainer container = objectContext.MetadataWorkspace.GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace);

    return container.BaseEntitySets
        .Where(x =>
            (x.ElementType.Name == type.Name) ||
            (x.ElementType.Name == type.BaseType?.Name) ||
            (x.ElementType.Name == type.BaseType?.BaseType?.Name)
        )
        .Select(x => x.Name)
        .FirstOrDefault() ?? throw new ArgumentException($"Specified type is not an entity type.", nameof(type));
}
Keith
  • 20,636
  • 11
  • 84
  • 125