Skip to content

Instantly share code, notes, and snippets.

@bjartwolf
Created March 21, 2024 08:46
Show Gist options
  • Save bjartwolf/87bc3d90038421a6e68abd8279bb13ee to your computer and use it in GitHub Desktop.
Save bjartwolf/87bc3d90038421a6e68abd8279bb13ee to your computer and use it in GitHub Desktop.
edmx builder
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using Microsoft.AspNet.OData.Builder;
using Microsoft.OData.Edm.Csdl;
using Microsoft.OData.Edm.Validation;
namespace foooo.Api.Odata
{
/// <summary>
/// Used to generate edmx metadata for Odata endpoints that are not handled by OData frameworks,
/// but by manually conmforming to the standard.
/// </summary>
public class CachedEdmxBuilder<T> where T : class
{
private readonly Lazy<string> _entityModel;
public CachedEdmxBuilder(string entityModelName)
{
_entityModel = new Lazy<string>(() => GenerateEdmx(entityModelName), true);
}
/// <summary>
/// Lazily return the OData model for samples pr day
/// </summary>
public string GetEdmx()
{
return _entityModel.Value;
}
private class Utf8StringWriter : StringWriter
{
public override Encoding Encoding => new UTF8Encoding(false);
}
/// <summary>
/// This is probably a bit expensive as it is using reflection and building up a model dynamically.
/// Therefore we cache it and do not expose it to the outside.
/// </summary>
private static string GenerateEdmx(string entitySetName)
{
var builder = new ODataConventionModelBuilder();
var typeOfModel = typeof(T);
builder.Namespace = typeOfModel.Namespace;
builder.EntitySet<T>(entitySetName);
builder.DataServiceVersion = new Version(4, 0);
var samplesModel = builder.GetEdmModel();
using (var stringWriter = new Utf8StringWriter())
{
using (var xmlWriter = XmlWriter.Create(stringWriter))
{
IEnumerable<EdmError> edmErrors;
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("edmx", "Edmx", "http://docs.oasis-open.org/odata/ns/edmx");
xmlWriter.WriteAttributeString("", "Version", "", "4.0");
xmlWriter.WriteStartElement("edmx", "DataServices", "http://docs.oasis-open.org/odata/ns/edmx");
var res = samplesModel.TryWriteSchema(xmlWriter, out edmErrors);
var edmErrorResult = edmErrors.ToList();
if (edmErrorResult.Count > 0 || !res)
{
throw new Exception(
$"Could not generate edmx model, {edmErrorResult.SelectMany(e => e.ErrorMessage.ToString())}");
}
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.Flush();
return stringWriter.ToString();
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment