【问题标题】:How to build EDM model for OData Web API in runtime?如何在运行时为 OData Web API 构建 EDM 模型?
【发布时间】:2015-03-27 20:10:14
【问题描述】:
我需要通过 OData 公开的实体是完全动态的(例如,用户可以配置他想要公开的字段)。来自存储库的查询结果存储在具有实际数据字典(字段名/值)的特殊泛型类中,因此 CLR 类型适用于所有类型。我完全了解实体(实体名称、实体字段及其类型)。
因此,我无法在设计时使用 ODataModelBuilder 方法构建 EDM 模型,例如 Entity、EntitySet 或 HasKey()、EntityTypeConfiguration 中的 Property()。
是否可以从头开始构建 EDM 模型? ODataModelBuilder 使用 EntityTypeConfiguration,但它取决于实体的 CLR 类型。基本上我需要用一种 CLR 类型声明几种实体类型。
请指教。
【问题讨论】:
标签:
odata
asp.net-web-api
asp.net-web-api2
【解决方案1】:
好的,所以我已经找到了这个问题的答案。
我编写了自己的 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;
}
【解决方案2】:
我就这样解决了这个问题,
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();
}