如何在运行时为OData Web API构建EDM模型?

时间:2015-01-28 19:14:10

标签: odata asp.net-web-api asp.net-web-api2

我有一个案例,我需要通过OData公开的实体是完全动态的(例如,用户可以配置他想要公开的字段)。来自存储库的查询结果存储在具有实际数据字典(FieldName / Value)的特殊泛型类中,因此CLR类型适用于所有类型。我对实体(实体名称,实体字段及其类型)有完整的了解。

因此我无法使用ODataModelBuilder方法(如Entity,EntitySet或HasKey(),EntityTypeConfiguration中的Property())在设计时构建EDM模型。

是否可以从头开始构建EDM模型? ODataModelBuilder使用EntityTypeConfiguration,但它依赖于实体的CLR类型。基本上我需要声明几种实体类型,所有实体类型都有一种CLR类型。

请告知。

2 个答案:

答案 0 :(得分:9)

好的,所以我已经找到了解决这个问题的答案。

我编写了自己的OData模型构建器,它使用了Microsoft.Data.Edm.Library命名空间(EdmModel,EdmEntityType等)中的类型。

示例:

public IEdmModel GetEdmModel()
{
    EdmModel model = new EdmModel();

    EdmEntityContainer container = new EdmEntityContainer(Namespace, "DefaultContainer");
    model.AddElement(container);
    model.SetIsDefaultEntityContainer(container, isDefaultContainer: true);

    EdmEntityType edmType = new EdmEntityType(Namespace, "Foo");
    EdmStructuralProperty idProp = edmType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.Int32), false);
    edmType.AddKeys(idProp);

    сontainer.AddEntitySet("MyEntitySet", edmType);

    model.SetDataServiceVersion(new Version(3, 0, 0, 0));
    model.SetMaxDataServiceVersion(new Version(3, 0, 0, 0));

    return model;
}

答案 1 :(得分:0)

我这样解决了这个问题,

private static IEdmModel GetEdmModel()
{
      ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
      builder.Namespace = "WebAPI";
      builder.ContainerName = "DefaultContainer";
      builder.EnableLowerCamelCase();

      foreach (Type item in GetTypesInNamespace(System.Reflection.Assembly.Load("ProjectDLL"), "NamespaceOfModels"))
      {
           //My models have a key named "Id"
           if (item.GetProperty("Id") == null)
               continue;

           EntityTypeConfiguration entityType = builder.AddEntityType(item);
           entityType.HasKey(item.GetProperty("Id"));
           builder.AddEntitySet(item.Name,entityType);
      }

      return builder.GetEdmModel();
}

在示例命名空间中获取类型

private static Type[] GetTypesInNamespace(System.Reflection.Assembly assembly, string nameSpace)
{
      return assembly.GetTypes()
             .Where(t => String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal))
             .ToArray();
}