如何通过EdmBuilder为OData v3 / BreezeJS从EF DBContext生成有效的元数据

时间:2015-01-21 22:03:19

标签: entity-framework metadata odata breeze

我正在尝试编写一个用于.NET4应用程序的OData v3后端。我想在客户端使用BreezeJS。对于服务器/ OData实现,我使用ODataLib v1-3。

为了生成现有模型的元数据,我遵循了以下指南:http://www.getbreezenow.com/documentation/ef-design-tool

(更具体地说,“仅元数据的DbContext”部分)

描述了如何使用Entity Framework作为设计时工具来生成IEdmModel和元数据。我使用BreezeJS Server Labs存储库中的EdmBuilder。

所有依赖项都是通过Nuget安装的:

  • Breeze Labs EdmBuilder(1.05)
  • OData v1-3的ODataLib(5.63)
  • EdmLib for OData v1-3(5.63)
  • EntityFramework(6.12)

好消息是:我可以生成元数据并将其发送给客户。

坏消息是:在使用带有OData配置的BreezeJS时负责解析元数据的DataJs不接受元数据。

问题是:有人在root xml元素中设置了错误的EDMX版本,而不是我。这导致DataJs丢弃接收的元数据。 v3的EDMX版本应为OData v3 specs中定义的1.0。

我没有想法(除了“手动”替换它)关于如何做到这一点,如果我遇到了死胡同。手动执行元数据并不是一个选择,因为我需要一个可维护的解决方案。

生成的元数据:

<edmx:Edmx Version="3.0" xmlns:edmx="http://schemas.microsoft.com/ado/2009/11/edmx">
    <edmx:DataServices m:DataServiceVersion="3.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
        <Schema Namespace="ODataMetaDataGenerator" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">

              [... schema content left out for brevity ...]

        </Schema>
    </edmx:DataServices>
</edmx:Edmx>

修改 更新我发现的内容: Breeze Server Labs的EdmBuilder正在使用EdmxWriter,后者又使用EdmxSerializer。根据所涉及的EdmModel的SchemaVersion,有一些代码可以确定命名空间。

System.Data.Entity.ModelConfiguration.Edm.Serialization.EdmxSerializer

public void Serialize(DbDatabaseMapping databaseMapping, XmlWriter xmlWriter)
 {
      this._xmlWriter = xmlWriter;
      this._databaseMapping = databaseMapping;
      this._version = databaseMapping.Model.SchemaVersion;
      this._namespace = object.Equals((object) this._version, (object) 3.0) ? "http://schemas.microsoft.com/ado/2009/11/edmx" : (object.Equals((object) this._version, (object) 2.0) ? "http://schemas.microsoft.com/ado/2008/10/edmx" : "http://schemas.microsoft.com/ado/2007/06/edmx");
      this._xmlWriter.WriteStartDocument();
      using (this.Element("Edmx", "Version", string.Format((IFormatProvider) CultureInfo.InvariantCulture, "{0:F1}", new object[1]
      {
        (object) this._version
      })))
      {
        this.WriteEdmxRuntime();
        this.WriteEdmxDesigner();
      }
      this._xmlWriter.WriteEndDocument();
      this._xmlWriter.Flush();
}

我可以以任何方式影响SchemaVersion吗?


更新

我找到了一个解决方法,涉及在Breeze的EdmBuilder生成的EdmModel上手动设置EdmxVersion:

    /// <summary>
    ///     Builds an Entity Data Model (EDM) from an
    ///     existing <see cref="DbContext" /> created using Code-First.
    ///     Use <see cref="GetModelFirstEdm" /> for a Model-First DbContext.
    /// </summary>
    /// <typeparam name="T">Type of the source <see cref="DbContext" /></typeparam>
    /// <param name="dbContext">Concrete <see cref="DbContext" /> to use for EDM generation.</param>
    /// <returns>An XML <see cref="IEdmModel" />.</returns>
    private static IEdmModel GetCodeFirstEdm<T>(this T dbContext) where T : DbContext
    {
        using (var stream = new MemoryStream())
        {
            using (var writer = XmlWriter.Create(stream))
            {
                EdmxWriter.WriteEdmx(dbContext, writer);
            }
            stream.Position = 0;
            using (var reader = XmlReader.Create(stream))
            {
                IEdmModel model = EdmxReader.Parse(reader);

                // this line sets the edmx version manually
                // can also happen outside of this implementation but maybe it is a general fix?
                model.SetEdmxVersion(new Version(1, 0)); 

                return model;
            }
        }
    }

仍需要验证现在是否正常。将报告回来。


更新

元数据似乎正在运行,但现在我的模型中的Enums存在问题,导致Breeze客户端出现异常。目前正在调试,以便更好地了解发生的事情。

为新问题打开了一个新问题: Exception while parsing metadata in BreezeJS client

0 个答案:

没有答案