Structural Annotations - One Pager
In V1 of the Entity Framework it is possible to annotate a schema using attributes declared in another XSD.
However XML attributes are a very limited form of annotation. It would be better if we could annotate using full elements.
This is what we are calling Structural Annotations.
This feature will allow both customers and partners like Reporting Services to modify the model so that it includes information important to them which can’t be captured in vanilla EDM format.
1 EDM extensions
While it should be possible to annotate any level in the XML hierarchy, there are however some restrictions.
The general rule is you can annotation any CSDL / SSDL element that has a corresponding MetadataItem which in practice means everything except <Using>, <Schema>, <Key> and <PropertyRef> elements.
These annotations should be named, so that they can be accessed using the same API as today.
i.e. something like this:
<EntityType Name="Content">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Guid" Nullable="false" />
<Property Name="HTML" Type="String" Nullable="false" MaxLength="Max" Unicode="true" FixedLength="false" />
<CLR:Attributes>
<CLR:Attribute TypeName="System.Runtime.Serialization.DataContract"/>
<CLR:Attribute TypeName="MyNamespace.MyAttribute"/>
</CLR:Attributes>
<RS:Security>
<RS:ACE Principal="S-0-123-1321" Rights="+R+W"/>
<RS:ACE Principal="S-0-123-2321" Rights="-R-W"/>
</RS:Security>
</EntityType>
1.1 Key points to notice:
- In the above example both the CLR and RS namespaces must have been declared somewhere. Probably at the root of the CSDL somewhere, i.e. something like this:
<Schema xmlns:RS="https://schemas.microsoft.com/RS/2006" xmlns:CLR=https://schemas.microsoft.com/net/3.5… - Alternatively the namespace could be in lined in the annotation:
<Security xmlns="https://schemas.microsoft.com/RS/2006"> …
</Security> - In both cases the unique identity of the annotation is in the form {namespace}:{elementname} . So for the RS Security annotation example, irrespective of how the RS namespace is introduced the identity would be:
https://schemas.microsoft.com/RS/2006:Security - Structural annotations should always follow all other sub-elements i.e. when structurally annotating an <EntityType> element the annotation element should follow all <Key> <Property> and <NavigationProperty> elements.
- Attribute based annotations (as supported in V1 and used for things like CodeGen) are scoped to the same annotation identity namespace. Hence care should be taken to verify that annotations using either approach don’t have colliding identities.
- It should be possible to have more than one named “Structural Annotation” per CSDL (or SSDL) element. Indeed element names can collide so long as the combination of Namespace + Element Name is unique for a particular element (or more specifically each MetadataItem). This means for instance you can’t have two <RS:Security> elements under any one MetadataItem.
1.2 Positive and Negative Cases:
This:
<EntityType Name="Content" CLR:Attribute="Blah">
<CLR:Attributes>
<CLR:Attribute TypeName="System.Runtime.Serialization.DataContract"/>
</CLR:Attributes>
…would be invalid, because of the identity collision, likewise this would also be invalid:
<EntityType Name="Content" My:Attribute="Blah">
<CLR:Attributes>
<CLR:Attribute TypeName="System.Runtime.Serialization.DataContract"/>
</CLR:Attributes>
<CLR:Attributes>
<CLR:Attribute TypeName="MyNamespace.MyAttribute"/>
</CLR:Attributes>
where-as this is fine:
<EntityType Name="Content" My:Attribute="Blah">
<CLR:Attributes>
<CLR:Attribute TypeName="System.Runtime.Serialization.DataContract"/>
</CLR:Attributes>
<RS:Security>
<RS:ACE Principal="S-0-123-1321" Rights="+R+W"/>
<RS:ACE Principal="S-0-123-2321" Rights="-R-W"/>
</RS:Security>
… since all the above annotations have unique identities.
1.3 What can an <Annotation> contain?
A structural annotation is simply an XML element. As such it can be considered a root of an XML document that can contain any valid XML structures. These structures are simply ignored by the Entity Framework and Metadata APIs.
1.4 What elements can be annotated?
If an element in the CSDL or SSDL has a corresponding MetadataItem in the Metadata API that element should support structural annotations. Since <Using>, <Schema>, <Key> and <PropertyRef> elements have no corresponding MetadataItem(s) they don’t support structural annotations.
Notice while TypeUsage(s) have no CSDL representation today,they are MetadataItem(s) so they could in theory be annotated in the future. For example if a public mutable metadata API is produced.
2 Metadata API Changes:
In this example we are using the Entity Frameworks Metadata API to get the EdmType for an EntityType called Content. From that we then get the MetadataProperty called https://schemas.microsoft.com/RS/2006:Security:
EdmType contentType = metadataWorkspace.GetEdmType(“MyNamespace.Content”);
if (contentType.MetadataProperties.Contains(
"https://schemas.microsoft.com/RS/2006:Security")
{
MetadataProperty annotationProperty = contentType.MetadataProperties[ "https://schemas.microsoft.com/RS/2006:Security"];
object annotationValue = annotationProperty.Value;
//Do something...
}
Notice that the way you access structural annotations is the same as the way you access attribute annotations, i.e. by name/identity, in the MetadataProperties collection.
This of course means that their names can’t collide, name collisions should be picked up when metadata is loaded from persistent formats (like CSDL) or when annotations are created by hand in the any future mutable metadata API.
2.1 MetadataProperty TypeUsage
When creating a MetadataProperty to hold the XElement for the structural annotation, we need to assign a TypeUsage too. For V1 style attribute annotations, the TypeUsage we chose was based on Edm.String. Ideally we should use Edm.XML etc, but since this is not currently available, we will use Edm.String in the meantime. We have filled a bug to change this if/when [j1] XML becomes an EDM type.
3 What is the MetadataProperty.Value?
The Value of the MetadataProperty will be a XElement for structural annotations originating from CSDL.
So if you know that the annotation is a structural annotation you can access it like this:
MetadataProperty annotationProperty =
contentType.MetadataProperties["CLR:Attributes"];
XElement myAnnotation = annotationProperty.Value as XElement;
3.1 XElement is rooted at the <Annotation> element
The XElement returned will be the XElement containing everything including the structural annotation itself.
3.2 XElement is mutable
There is nothing to stop the consumer of the Metadata API from modifying the XElement since it is simply a reference, to an instance of a type the Entity Framework doesn’t control.
We could address this by cloning on access to make things a little safer. But this negatively affects the mainline scenario, namely where a customer uses annotations purely for read, and is therefore not required.
The important thing to understand is that should a user modify the XElement all bets are off. We should provide guidance both via API hints:
/// <summary>
/// ....
/// <remarks>
/// Should this return a reference type like an XElement, you should consider
/// this immutable, no guarantees are made about behavior if this reference
/// type is modified in anyway.
/// </remarks>
/// </summary>
public object Value { get {
And via appropriate documentation.
3.3 No universal annotation format
Rather than try to invent a new universal data format for annotations, we decided to be pragmatic.
So we are limiting ourselves to XML for structural annotations loaded from CSDL (an XML format).
However since the MetadataProperty.Value is of type object, in a world where we have an alternative EDM representation (like in memory using mutable metadata for instance) we could easily assign something other than an XElement to the MetadataProperty.Value, like for example a xaml Serializable CLR type instance.
4 Out of Scope
The current plan is to simply support annotation in the CSDL & SSDL. Meaning annotating MSL is currently out of scope.
If we uncover meaningful important scenarios for MSL annotations, we will undertake that work separately.
Incidentally supporting structural annotations in MSL touches a completely separate code path, and as a result will require roughly the same amount of work. Additionally in order to make undertaking this work meaningful we would first need to expose a public mapping metadata API.
....
As always we are keen to hear any feedback you have on this item.
Do you think you will find a use for Structured Annotations?
Alex James
Program Manager,
Entity Framework Team
This post is part of the transparent design exercise in the Entity Framework Team. To understand how it works and how your feedback will be used please look at this post .
Comments
Anonymous
August 12, 2008
PingBack from http://www.easycoded.com/structural-annotations-one-pagerAnonymous
August 26, 2008
EF needs better and easier metadata API, currently it's very hard and time consuming to browse through metadata and find meaningful information. (The documentation needs some improvement also). Entity Framework is a powerful new technology, that we are using for our new project that will be completed over the course of the following years (one to two years). We, the developers at my company, love EF, but it really needs some polishing in it's current state. The areas that need polishing are: the Visual Designer, Metada API and Code Generation; the rest is very solid and has allowed us to create an infrastructure for our application that we couldn't have dreamed about using other prior technologies from Mircrosoft, 3rd party or custom made. The Annotation features, will be absolutely great as long as the designer and code generation infrastructure can support them by default. Our edmx file already has 34500+ lines of code and it's impractical to edit it manually. Best wishes, A Entity Framework fan and supporter!Anonymous
January 06, 2009
If you look at the EDM and in particular the metadata it considers important, one thing is clear: Persistence