tabs ↹ over ␣ ␣ ␣ spaces

by Jiří {x2} Činčura

MetadataWorkspace in Entity Framework

14 Jun 2009 3 mins Entity Framework, LINQ

A lot of people get used to understand the ObjectStateManager class. Yep, it’s the place where all the change tracking magic happens. But there’s also one other place that’s interesting. It’s MetadataWorkspace. With this class’ properties and methods you can find almost everything about stuff in your model, in runtime.

The information inside MetadataWorkspace is among others organizes into so-called spaces (DataSpace enum). Probably CSpace and SSpace are the most used. The CSpace contains stuff you have in your conceptual model (what you see in designer) and SSpace contains stuff from store model, so the database “structure”.

The items in MetadataWorkspace can be anything from the Metadata Type Hierarchy (definitely look at this link) starting with GlobalItem. This contains i.e. EntityType, ComplexType or EdmFunction. These types inside are containing a lot of other useful information. Thus when you want to show i.e. all tables and primary keys for these tables you can use (don’t forgot to first, for example, query for one record to load metadata or use this trick):

MetadataWorkspace mw = ent.MetadataWorkspace;
var items = mw.GetItems<EntityType>(DataSpace.SSpace);
foreach (var i in items)
{
    Console.WriteLine("Table Name: {0}", i.Name);
    Console.WriteLine("Keys:");
    foreach (var key in i.KeyMembers)
    {
        Console.WriteLine("t {0} ({1})", key.Name, key.TypeUsage.EdmType.FullName);
    }
}

I’m first asking for all entity types from store space, which gives us all tables there. Then I’m simply inspecting the properties to get some useful info – first the name of table and then all key members reading name and type (EdmType). Also the MetadataProperties is definitely worth looking (see below). It’s just a tip of an iceberg, and that was not difficult. You can literally get any information you’ve ever seen in your model.

And not only what you’ve seen in your model directly. For instance, the provider may expose some store specific functions you can use in ESQL queries. So the code:

var functions = mw.GetItems<EdmFunction>(DataSpace.SSpace);
foreach (EdmFunction function in functions.Where(f => (bool)f.MetadataProperties["BuiltInAttribute"].Value))
{
    Console.WriteLine(function.FullName);
}

Gives you all of these functions. If you remove the condition you’ll get all functions, including stored procedures of user defined functions. Wanna parameters of these functions? No problem, it’s there. Just check Parameters property.

And that’s only the SSpace. The conceptual part of model is described there too. To see how much is the model interconnected (i.e. to consider pregenerating views) simply run:

var entities = mw.GetItems<EntityType>(DataSpace.CSpace);
foreach (var entity in entities)
{
    Console.WriteLine("Table Name: {0}", entity.Name);
    Console.WriteLine("Navigation Properties#: {0}", entity.NavigationProperties.Count);
}

Interesting may be also the object model aka objects created from conceptual model. Although I can continue with some more or less useful examples – to see all to posibilities (and also hit the accessibility limitations), try it yourself. And if you stuck, feel free to ask (here or in forums).

Profile Picture Jiří Činčura is .NET, C# and Firebird expert. He focuses on data and business layers, language constructs, parallelism, databases and performance. For almost two decades he contributes to open-source, i.e. FirebirdClient. He works as a senior software engineer for Microsoft. Frequent speaker and blogger at www.tabsoverspaces.com.