Search code examples
c#.netodatawcf-data-services

Using IEdmModel to resolve EntitySet name into EntityName (Products -> Product)


I am using a OData Service on top of Entity Framework

var uri = new Uri("http://localhost:9876/Service.svc");
var context = new DataServiceContext(uri, , DataServiceProtocolVersion.V3);
var model = EdmxReader.Parse(
    XmlReader.Create(context.GetMetadataUri().AbsoluteUri)
);
context.Format.UseJson(model);

Now I need to figure out the entity name name from an EntitySet name

My entities are called Product or Customer but the Name of the EntitySet can be either Products or CustomerSet or something else.

Since I already loaded the IEdmModel and the information is located in the $metadata is there a way to resolve the entity name from the IEdmModel?


Solution

  • Since I haven't found a way to extract the information I want I ended up creating my own solution.

    First I read the metadata xml into a string to only have a roundtrip to the service. Then I create my IEdmModel from the string and create my own class which extracts all information from the metadata xml.

        var client = new WebClient();
        var metadata = client.DownloadString(metadataUri);
        var model = CreateModel(metadata);
        var schema = CreateSchema(metadata);
    
        private static IEdmModel CreateModel(string metadata)
        {
            using (var reader = new StringReader(metadata))
            using (var xmlReader = XmlReader.Create(reader))
            {
                return EdmxReader.Parse(xmlReader);
            }
        }
    
        private static Schema.Schema CreateSchema(string metadata)
        {
            using (var reader = new StringReader(metadata))
            using (var xmlReader = XmlReader.Create(reader))
            {
                var root = XElement.Load(xmlReader);
                return SchemaBuilder.GetSchema(root);
            }
        }
    

    Here is the code to read the Schema from the metadata, hopefully someone will find this useful. I did not include the classes I use but they are just POCOS with no code.

        public static Schema GetSchema(XElement root)
        {
    
            XNamespace edmx = root.GetNamespaceOfPrefix("edmx");
            XNamespace edm = root.Element(edmx + "DataServices").Elements().First().GetDefaultNamespace();
    
            var result = from s in root.Element(edmx + "DataServices").Elements(edm + "Schema")
                         select new
                         {
                             Namespace = (string)s.Attribute("Namespace"),
                             EntityTypes = from e in s.Elements(edm + "EntityType")
                                           select new EntityType
                                           {
                                               Name = (string)e.Attribute("Name"),
                                               Key = from k in e.Element(edm + "Key").Elements(edm + "PropertyRef")
                                                     select (string)k.Attribute("Name"),
                                               Properties = from p in e.Elements(edm + "Property")
                                                            select new Property
                                                            {
                                                                Name = (string)p.Attribute("Name"),
                                                                Type = (string)p.Attribute("Type"),
                                                                Nullable = (bool)p.Attribute("Nullable", true),
                                                                MaxLength = (string)p.Attribute("MaxLength"),
                                                                FixedLength = (bool)p.Attribute("FixedLength", false),
                                                            },
                                               NavigationProperties = from p in e.Elements(edm + "NavigationProperty")
                                                                      select new NavigationProperty
                                                                      {
                                                                          Name = (string)p.Attribute("Name"),
                                                                          Relationship = (string)p.Attribute("Relationship"),
                                                                          ToRole = (string)p.Attribute("ToRole"),
                                                                          FromRole = (string)p.Attribute("FromRole"),
                                                                      }
                                           },
                             Associations = from a in s.Elements(edm + "Association")
                                            select new Association
                                            {
                                                Name = (string)a.Attribute("Name"),
                                                Ends = from et in a.Elements(edm + "End")
                                                       select new AssociationEnd
                                                       {
                                                           Type = (string)et.Attribute("Type"),
                                                           Role = (string)et.Attribute("Role"),
                                                           Multiplicity = (string)et.Attribute("Multiplicity"),
                                                       }
                                            },
                             AssociationSets = from @as in s.Elements(edm + "EntityContainer").Elements(edm + "AssociationSet")
                                               select new AssociationSet
                                               {
                                                   Name = (string)@as.Attribute("Name"),
                                                   Association = (string)@as.Attribute("Association"),
                                                   Ends = from r in @as.Elements(edm + "End")
                                                          select new AssociationSetEnd
                                                          {
                                                              Role = (string)r.Attribute("Role"),
                                                              EntitySet = (string)r.Attribute("EntitySet"),
                                                          },
                                               },
                            EntitySets = from @es in s.Elements(edm + "EntityContainer").Elements(edm + "EntitySet")
                                         select new EntitySet
                                                {
                                                    Name = (string)@es.Attribute("Name"),
                                                    EntityType = (string)@es.Attribute("EntityType"),
                                                },
    
                         };
    
            return new Schema
            {
                Namespace = result.First().Namespace,
                EntityTypes = result.SelectMany(x => x.EntityTypes).ToDictionary(x => x.Name),
                Associations = result.SelectMany(x => x.Associations).ToDictionary(x => x.Name),
                AssociationSets = result.SelectMany(x => x.AssociationSets).ToDictionary(x => x.Name),
                EntitySets = result.SelectMany(x => x.EntitySets).ToDictionary(x => x.Name),
            };
        }