Search code examples
f#odata

How do I walk the Odata entity model graph?


#r "nuget: Microsoft.OData.Edm"

open Microsoft.OData.Edm
open System.Xml

let reader = XmlReader.Create("metadata.xml")
let success, edmModel, errors  = Csdl.CsdlReader.TryParse(reader)

let container = edmModel.EntityContainer
let elements = edmModel.SchemaElements |> Seq.cast<IEdmSchemaElement> |> Array.ofSeq

for elem in elements do
    printfn $"1  {elem.Name} : {elem.SchemaElementKind} : {elem.Location()}"

let entitySets = container.EntitySets() |> Seq.cast<IEdmEntitySet> |> Array.ofSeq

for elem in entitySets do
    let cElems = elem.Container.Elements |> Seq.cast<IEdmEntityContainerElement> |> Array.ofSeq
    printfn $"   2  {elem.Name} : {elem.ContainerElementKind}"

    for celem in cElems do
        printfn $"      3  {celem.Name} : {celem.ContainerElementKind}"

This is the extent to which I can walk an odata entity model graph with Microsoft.OData.Edm. The results of the level 2 and 3 prints are the same. I want to access the keys and properties of the entity types.

I can always switch to walking the XML graph, but using a maintained odata library seems like the right thing to do.


Solution

  • I think the trick here is to downcast the elements to IEdmEntityType where possible:

    let entTypes =
        edmModel.SchemaElements
            |> Seq.choose (function
                | :? IEdmEntityType as entType -> Some entType
                | _ -> None)
    for entType in entTypes do
        printfn "%s" entType.Name
        for prop in entType.DeclaredProperties do
            printfn "   %s %s" prop.Name (prop.Type.ShortQualifiedName())
    

    Output will look something like:

    Product
       ID Int32
       Name String
       Description String
       ReleaseDate DateTimeOffset
       DiscontinuedDate DateTimeOffset
       Rating Int16
       Price Double
       Categories
       Supplier ODataDemo.Supplier
       ProductDetail ODataDemo.ProductDetail
    FeaturedProduct
       Advertisement ODataDemo.Advertisement
    ProductDetail
       ProductID Int32
       Details String
       Product ODataDemo.Product