Skip to content

Instantly share code, notes, and snippets.

@dariusclay
Last active December 1, 2022 22:35
Show Gist options
  • Save dariusclay/8673940 to your computer and use it in GitHub Desktop.
Save dariusclay/8673940 to your computer and use it in GitHub Desktop.
How to build OData IEdmModel from Entity Framework model
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Data.Entity;
using System.Data.Entity.Core.EntityClient;
using System.Data.Entity.Infrastructure;
using System.Diagnostics;
using System.Xml;
using Microsoft.Data.Edm;
using Microsoft.Data.Edm.Csdl;
using Microsoft.Data.Edm.Validation;
namespace ODataServices
{
public abstract class ODataEntityFrameworkModelBuilder
{
private const string CsdlFileExtension = ".csdl";
private const string EntityConnectionMetadataPatternText = @"^(res://\*/(?<name>[^\|]+))(\|res://\*/(?<name>[^\|]+)?)*$";
private const RegexOptions EntityConnectionMetadataRegexOptions =
RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture;
private static readonly Regex EntityConnectionMetadataPattern =
new Regex( EntityConnectionMetadataPatternText, EntityConnectionMetadataRegexOptions );
private static Stream GetCsdlStreamFromMetadata( IObjectContextAdapter context )
{
var metadata = new EntityConnectionStringBuilder( context.ObjectContext.Connection.ConnectionString ).Metadata;
return ( from Match match in EntityConnectionMetadataPattern.Matches( metadata )
from Capture capture in match.Groups[ "name" ].Captures
where capture.Value.EndsWith( CsdlFileExtension )
let assembly = Assembly.GetAssembly( context.GetType() )
select assembly.GetManifestResourceStream( capture.Value ) ).Single();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2202:Do not dispose objects multiple times" )]
public static IEdmModel GetEdmModel<T>() where T : DbContext, new()
{
using ( Stream csdlStream = GetCsdlStreamFromMetadata( new T() ) )
{
using ( XmlReader reader = XmlReader.Create( csdlStream ) )
{
IEdmModel model;
IEnumerable<EdmError> errors;
if ( !CsdlReader.TryParse( new[] { reader }, out model, out errors ) )
{
foreach ( var e in errors )
Debug.Fail( e.ErrorCode.ToString( "F" ), e.ErrorMessage );
}
return model;
}
}
}
}
}
using System;
using System.Linq;
using System.Collections.Generic;
using System.Web.Http;
using System.Web.Http.OData.Routing;
namespace ODataServices {
public static class WebApiConfig {
public static void Register( HttpConfiguration config ) {
// Enables OData support by adding an OData route and enabling querying support for OData.
config.Routes.MapODataRoute(
routeName: "ODataRoute",
routePrefix: "odata",
model: ODataEntityFrameworkModelBuilder.GetEdmModel<SomeDbContext>()
);
config.EnableQuerySupport();
// To disable tracing in your application, please comment out or remove the following line of code
config.EnableSystemDiagnosticsTracing();
}
}
}
@dariusclay
Copy link
Author

Works with ODataLib 5.6.0, EdmLib 5.6.0 and EntityFramework 6.0.2

@norcino
Copy link

norcino commented Sep 19, 2019

Very interesting, did you try the same with latest versions and .net Core?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment