如何在运行时为 OData Web API 构建 EDM 模型?
How to build EDM model for OData Web API in runtime?
我有一个案例,我需要通过 OData 公开的实体是完全动态的(例如,用户可以配置他想要公开的字段)。来自存储库的查询结果存储在具有实际数据字典 (FieldName/Value) 的特殊泛型 class 中,因此 CLR 类型是通用的。我完全了解实体(实体名称、实体字段及其类型)。
因此,我无法在设计时使用 Entity、EntitySet 或 HasKey() 等 ODataModelBuilder 方法构建 EDM 模型,属性() 来自 EntityTypeConfiguration。
是否可以从头开始构建 EDM 模型? ODataModelBuilder 使用 EntityTypeConfiguration,但它取决于实体的 CLR 类型。基本上我需要用一种 CLR 类型声明几种实体类型。
请指教
好的,所以我找到了这个问题的答案。
我编写了自己的 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;
}
我就这样解决了这个问题,
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();
}
我有一个案例,我需要通过 OData 公开的实体是完全动态的(例如,用户可以配置他想要公开的字段)。来自存储库的查询结果存储在具有实际数据字典 (FieldName/Value) 的特殊泛型 class 中,因此 CLR 类型是通用的。我完全了解实体(实体名称、实体字段及其类型)。
因此,我无法在设计时使用 Entity、EntitySet 或 HasKey() 等 ODataModelBuilder 方法构建 EDM 模型,属性() 来自 EntityTypeConfiguration。
是否可以从头开始构建 EDM 模型? ODataModelBuilder 使用 EntityTypeConfiguration,但它取决于实体的 CLR 类型。基本上我需要用一种 CLR 类型声明几种实体类型。
请指教
好的,所以我找到了这个问题的答案。
我编写了自己的 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;
}
我就这样解决了这个问题,
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();
}