locked
Trying to understand how to use Microsoft.Data.Edm RRS feed

  • Question

  • Hi all;

    First off, when do you think you will document the classes and how to use them? It's really hard to figure out when there is no documentation.

    I think the way to read a url like http://services.odata.org/OData/OData.svc/$metadata is with EdmxReader.TryParse(). That works. However, the returned IEdmModel does not seem to provide the full structure (looking at the returned properties in the debugger):

    1. It should have the DataServices node as a property or at least it's m:DataServiceVersion. Where is that?
    2. It should have an IEnumerable<> of schemas. It has SchemaElements but those appear to be EntityType definitions, not Schema node representatives. Does it mix all EntityTypes across all Schema's in this collection and we then use the Namespace property to break them out?
    3. How do I pull the associations out of this? There is a private variable CsdlSemanticsModel.associationDoctionary in the IEdmModel returned, but no way to access it.
    4. Where are the ComplexTypes defined in all of this?

    thanks - dave


    Who will win The International Collegiate Programming Championships?

    Monday, July 23, 2012 6:25 PM

Answers

  • 1. The DataService node is just a serialization detail, the model itself doesn't have any notion of it. The m:DataServiceVersion is stored as an annotation on the IEdmModel itself. You can access it using the Microsoft.Data.Edm.Csdl.SerializationExtensionmethods.GetDataServiceVersion method. (There's also GetMaxDataServiceVersion for the m:MaxDataServiceVersion attribute).

    2. The Schema elements are also a serialization detail. What matters are the namespaces. It is possible to have multiple Schema elements targeting the same namespace, so that's another reason to not expose them. As a result what you do have is the SchemaElements which is an enumeration of all the items which occur under the Schema. Each of them has a Namespace property. SchemaElements are types, entity containers and so on. If you need to have a list of namespaces, you will need to reconstruct it from all the elements.

    3. The associations and association sets are processed and modeled through navigation properties. So each navigation property can get your the multiplicity and type of it (The type of the other side is just IEdmNavigationProperty.Type, the multiplicity can be deduced from the type as well. If it's a collection then it was 1 to Many, if it's a singleton which is non-nullable then it was 1 if it's nullable it was 0). The association sets are accessible through IEdmEntitySet.FindNavigationTarget. Given the navigation property on the type in the set, this gets you the entity set of the other side of that navigation. This makes it easier to walk the model, otherwise you would have to perform the lookups into the association types and sets yourself which is somewhat tricky.

    4. Complex types are just types and they are schema elements. So you enumerate the SchemaElements, some of them are going to be IEdmEntityType others IEdmComplexType and so on.

    One important note: In theory EDM models can refer to other EDM models. As a result if you load a model the IEdmModel you get back is just one of several (the referenced ones are in IEdmModel.ReferencedModels). To get 100% correct view you need to combine them all into "one". For this purpose there are extension methods to help you do this. So instead of accessing SchemaElements it is probably better to use ExtensionMethods.SchemaElementsAcrossModels (which merges all the SchemaElements collections from all the models for you). If you're going to be walking the model, then getting the combined view of the schema elements if probably all you need (any given type can only occur in a single model).

    Thanks,


    Vitek Karas [MSFT]

    • Marked as answer by DavidThielen Tuesday, July 24, 2012 6:13 PM
    Monday, July 23, 2012 8:12 PM
    Moderator
  • 1 & 2: Actually there is an EntityContainer node (don't ask me why there's no Schema but there is EntityContainer, I'm sure there is a reason, I just don't know it :-)). EntityContainer is a SchemaElement so it belongs to a namespace. It itself then contains entity sets (which are not SchemElements since they have to belong to an entity container).

    4: If you get the IEdmComplexType that describes the complex type. I guess I don't understand what you're looking for. The IEdmComplexType has the list of properties declared on the complex type, its name and so on.

    Thanks,


    Vitek Karas [MSFT]

    • Marked as answer by DavidThielen Tuesday, July 24, 2012 6:13 PM
    Tuesday, July 24, 2012 9:23 AM
    Moderator
  • As noted in the other thread, I think that you might choose to only use the default entity container.

    The other way to do this might be to request the service document (the response you get when you hit the root of the service: http://services.odata.org/V3/OData/OData.svc/ ). The purpose of this document is to advertise all the entity sets you can use. ODataLib can read this for you (ReadServiceDocument). In most services the list of entity sets will be the same as the entity sets in the default container (WCF DS doesn't allow anything else currently).

    Thanks,


    Vitek Karas [MSFT]

    • Marked as answer by DavidThielen Tuesday, July 24, 2012 6:13 PM
    Tuesday, July 24, 2012 5:38 PM
    Moderator

All replies

  • You can start with the OData T4 which uses EdmLib to walk the model and generate the client side classes for it. https://www.nuget.org/packages/Microsoft.Data.Services.Client.T4/

    I will try to answer your questions a bit later...

    Thanks,


    Vitek Karas [MSFT]

    Monday, July 23, 2012 7:31 PM
    Moderator
  • Thank you. I'm hoping we don't have to dive into the source because that will add a ton of time using your library. (This is why I try to avoid open source - I want documentation so I can use a library quickly.)

    For the metadata a simple command line example program that reads the metadata and then writes it out would be gigantic.

    thanks - dave


    Who will win The International Collegiate Programming Championships?


    Monday, July 23, 2012 7:59 PM
  • 1. The DataService node is just a serialization detail, the model itself doesn't have any notion of it. The m:DataServiceVersion is stored as an annotation on the IEdmModel itself. You can access it using the Microsoft.Data.Edm.Csdl.SerializationExtensionmethods.GetDataServiceVersion method. (There's also GetMaxDataServiceVersion for the m:MaxDataServiceVersion attribute).

    2. The Schema elements are also a serialization detail. What matters are the namespaces. It is possible to have multiple Schema elements targeting the same namespace, so that's another reason to not expose them. As a result what you do have is the SchemaElements which is an enumeration of all the items which occur under the Schema. Each of them has a Namespace property. SchemaElements are types, entity containers and so on. If you need to have a list of namespaces, you will need to reconstruct it from all the elements.

    3. The associations and association sets are processed and modeled through navigation properties. So each navigation property can get your the multiplicity and type of it (The type of the other side is just IEdmNavigationProperty.Type, the multiplicity can be deduced from the type as well. If it's a collection then it was 1 to Many, if it's a singleton which is non-nullable then it was 1 if it's nullable it was 0). The association sets are accessible through IEdmEntitySet.FindNavigationTarget. Given the navigation property on the type in the set, this gets you the entity set of the other side of that navigation. This makes it easier to walk the model, otherwise you would have to perform the lookups into the association types and sets yourself which is somewhat tricky.

    4. Complex types are just types and they are schema elements. So you enumerate the SchemaElements, some of them are going to be IEdmEntityType others IEdmComplexType and so on.

    One important note: In theory EDM models can refer to other EDM models. As a result if you load a model the IEdmModel you get back is just one of several (the referenced ones are in IEdmModel.ReferencedModels). To get 100% correct view you need to combine them all into "one". For this purpose there are extension methods to help you do this. So instead of accessing SchemaElements it is probably better to use ExtensionMethods.SchemaElementsAcrossModels (which merges all the SchemaElements collections from all the models for you). If you're going to be walking the model, then getting the combined view of the schema elements if probably all you need (any given type can only occur in a single model).

    Thanks,


    Vitek Karas [MSFT]

    • Marked as answer by DavidThielen Tuesday, July 24, 2012 6:13 PM
    Monday, July 23, 2012 8:12 PM
    Moderator
  • 1. & 2. - Ok, that makes sense. Treat it all as one database with multiple schemas. This means no object for the EntityContainer node too - correct?

    3. Ok, thank you.

    4. But I need the structure/definition of the ComplexType so I know what's in it. Is that available anywhere?

    thanks - dave


    Who will win The International Collegiate Programming Championships?

    Monday, July 23, 2012 9:02 PM
  • 1 & 2: Actually there is an EntityContainer node (don't ask me why there's no Schema but there is EntityContainer, I'm sure there is a reason, I just don't know it :-)). EntityContainer is a SchemaElement so it belongs to a namespace. It itself then contains entity sets (which are not SchemElements since they have to belong to an entity container).

    4: If you get the IEdmComplexType that describes the complex type. I guess I don't understand what you're looking for. The IEdmComplexType has the list of properties declared on the complex type, its name and so on.

    Thanks,


    Vitek Karas [MSFT]

    • Marked as answer by DavidThielen Tuesday, July 24, 2012 6:13 PM
    Tuesday, July 24, 2012 9:23 AM
    Moderator
  • 1 & 2: Is there any reason to look at the EntityContainer? Or is it just another view of the info I have?

    4: Got it - I didn't dive deep enough into the properties to find that. You are correct - that info is there.

    thanks - dave


    Who will win The International Collegiate Programming Championships?

    Tuesday, July 24, 2012 4:32 PM
  • As noted in the other thread, I think that you might choose to only use the default entity container.

    The other way to do this might be to request the service document (the response you get when you hit the root of the service: http://services.odata.org/V3/OData/OData.svc/ ). The purpose of this document is to advertise all the entity sets you can use. ODataLib can read this for you (ReadServiceDocument). In most services the list of entity sets will be the same as the entity sets in the default container (WCF DS doesn't allow anything else currently).

    Thanks,


    Vitek Karas [MSFT]

    • Marked as answer by DavidThielen Tuesday, July 24, 2012 6:13 PM
    Tuesday, July 24, 2012 5:38 PM
    Moderator