Open qwertie opened 2 years ago
@qwertie
for the #1, you can do like (pseudocode codes).
....
EdmModel model = builder.GetEdmModel() as EdmModel;
var entityType = model.SchemaElements.OfType<IEdmEntityType>().First(e => e.Name == "ODataEntity");
IODataTypeMapper mapper = model.GetTypeMapper();
foreach (var fds in cusomFields)
{
// get the Edm type from the CLR type, make sure the corresponding Edm type is defined already in the model.
var fdEdmType = mapper.GetEdmTypeReference(model, fds.Type);
entityType.AddStructuralProperty(fds.Name, fdEdmType);
}
return model;
For your second question, can you share more details about what you want to do?
Thank you. Unfortunately, code like that doesn't work. The problem is that when the data endpoint is accessed, Microsoft.AspNetCore.OData.Formatter.ResourceContext.GetPropertyValue
is called for every property in the EDM model, which calls TypedEdmStructuredObject.TryGetPropertyValue
, which returns null because it's not a CLR property, and then ResourceContext.GetPropertyValue
throws an exception like InvalidOperationException
: 'The EDM instance of type '[ODataEntity Nullable=True]' is missing the property 'ExampleCustomField'.'
For your second question, can you share more details about what you want to do?
It's very simple. Sometimes a user will create (or remove) custom fields. When this happens, the metadata returned from https://.../odata/$metadata must also change.
@qwertie For the first issue, you can create/customize the resource serializer to provide the property value.
For the second, you can replace the built-in MetadataRoutingConvention to provide the change model.
How does one create/customize the resource serializer?
@qwertie https://devblogs.microsoft.com/odata/build-formatter-extensions-in-asp-net-core-odata-8-and-hooks-in-odataconnectedservice/ is a post illustrating how to create the serializer. Let me know if it can't work and need further help.
The dynamic example gives you all the code you need to have dynamic metadata generation, the class you are looking for that ties it together is MyODataRoutingMatcherPolicy. As for the model generation I ended up using the TypeExtender nuget package and used that to add the additional fields to the base class.
When creating your OData connection to the feed are you selecting the checkbox to include open type properties
.
I realize that there is a sample here for creating 100% dynamic models. However, in our case we have an existing model that we are happy with, but we want to add custom fields to it.
In other words, we want an OData model with entities that have some fixed columns/properties and some dynamically-generated columns/properties that come from the database, like this:
To my tremendous surprise, the key-value pairs in
CustomFields
become properties in the JSON output (i.e. there is noCustomFields
column; its contents are inserted into the parent object). However, the custom fields are not recognized by Power BI:I assume that this is because there is no metadata for the custom fields in https://.../odata/$metadata. So my question is:
How can I modify the following code so that the custom columns are included in the
IEdmModel
?How can I modify the following startup code so that the
IEdmModel
is regenerated every time https://.../odata/$metadata is accessed?Edit: mirrored on SO