You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a feature request that resulted from my investigations done in #1629. As I am currently working on a prototype of a new API I will likely attempt to adapt parts of the framework to implement this feature request until some extend. I hope the team working on this project can give some feedback if such a change to the library is something you want to follow up.
Introduction
Currently internally the framework assumes that 1 CLR type will only be used to provide 1 EDM type. All mappings happen on a 1:1 basis but this might not always be the case. If you use a "sparse column" system as alternative to a Entity-Attribute-Value model, 1 table in the database (e.g. Entity) might contain different type of entites. In this case you might end up with 2 instances of the Entity class representing different kinds of semantic models.
As many of you might know, an EAV system is a nightmare to operate (development, performance, and maintenance wise). A data model defining general-purpose columns is also not the golden solution but solves many problems at the cost of lacking normalization. Many people sooner or later come to the point where such a requirement needs to be realized, but not many frameworks have the required features to realize this in a good manner.
Use Case
Lets assume you define a entity which has a set of general purpose string and int properties that are filled depending on your entity definitions. And one property defining what kind of entity you have. In a real world application the entity type would actually be a DB level definition of the entity.
On DB level you might have:
Id
EntityType
StringValue1
IntValue1
1
Person
Daniel
28
2
Building
Building 04
4
Which would be represented by objects:
new Entity {Id=1,EntityType="Person",StringValue1="Daniel",IntValue1=28},new Entity {Id=2,EntityType="Building",StringValue1="Building 04",IntValue1=4}
On API those would actually be 2 different EDM types
The framework needs a possibility where an instance can control what kind of EDM type it actually is. Theoretically the IEdmObject would define a GetEdmType which allows an instance of a class to provide the underlying IEdmType. But this interface is actually used in different ways. It switches the whole OData framework into a untyped mode where a lot of functionality is lost.
Instead the framework should provide some systems where on collections and on instances the developer can tell what EdmType is represented by the contents. Several places in the code are based on the raw CLR types without considering that instances might not directly map to a EDM type by their type. Just to name a few:
Microsoft.AspNet.OData.Formatter.ClrTypeCache
EdmLibHelpers.GetEdmType
EnableQuery.GetElementType
ODataSetResourceSerializer
ODataResourceSerializer
At the places where a EDM type is resolved for a CLR type (or vice versa) e.g. the IEdmModel should be asked to translate it to a EdmType. Currently a lot of this functionality is implemented in internal extension methods (mostly in EdmLibHelpers) and can not be changed/extended. Also, where possible, rather the actual object should be used for the translation than its type loaded via GetType(). A custom IEdmModel implementation (or a special one provided by the framework) can then do the correct translation between CLR objects/types and EDM types.
A EDM model construction could look like this:
varpersonType= conventionModelBuilder.AddEntityType<Entity>("Person");// name is already required on adding to support multiple registrations
personType.Namespace ="My.Models";
personType.IdentifiedBy(x => x.EntityType =="Person");
personType.ComplexProperty(x => x.String1).Name ="Name";
personType.ComplexProperty(x => x.Int1).Name ="Age";varbuildingType= conventionModelBuilder.AddEntityType<Entity>("Building");
buildingType.Namespace ="My.Models";
buildingType.IdentifiedBy(x => x.EntityType =="Building");
buildingType.ComplexProperty(x => x.String1).Name ="Name";
buildingType.ComplexProperty(x => x.Int1).Name ="Levels";
For queryables/enumerables there could be a extension method which creates a "wrapper" IQueryable which annotates the original query with the edm types contained. This would allow polymorphic collections but also on strictly type collections the base type is defined.
That should give a first basic picture. A final implementation will likely need way more adjustments to ensure the mappings and object constructions work as expected everywhere. With this mapping in place also all other functionality ($filter, $select etc.) will work via the normal property aliasing.
The text was updated successfully, but these errors were encountered:
This is a feature request that resulted from my investigations done in #1629. As I am currently working on a prototype of a new API I will likely attempt to adapt parts of the framework to implement this feature request until some extend. I hope the team working on this project can give some feedback if such a change to the library is something you want to follow up.
Introduction
Currently internally the framework assumes that 1 CLR type will only be used to provide 1 EDM type. All mappings happen on a 1:1 basis but this might not always be the case. If you use a "sparse column" system as alternative to a Entity-Attribute-Value model, 1 table in the database (e.g. Entity) might contain different type of entites. In this case you might end up with 2 instances of the Entity class representing different kinds of semantic models.
As many of you might know, an EAV system is a nightmare to operate (development, performance, and maintenance wise). A data model defining general-purpose columns is also not the golden solution but solves many problems at the cost of lacking normalization. Many people sooner or later come to the point where such a requirement needs to be realized, but not many frameworks have the required features to realize this in a good manner.
Use Case
Lets assume you define a entity which has a set of general purpose string and int properties that are filled depending on your entity definitions. And one property defining what kind of entity you have. In a real world application the entity type would actually be a DB level definition of the entity.
On DB level you might have:
Which would be represented by objects:
On API those would actually be 2 different EDM types
Proposal
The framework needs a possibility where an instance can control what kind of EDM type it actually is. Theoretically the
IEdmObject
would define aGetEdmType
which allows an instance of a class to provide the underlyingIEdmType
. But this interface is actually used in different ways. It switches the whole OData framework into a untyped mode where a lot of functionality is lost.Instead the framework should provide some systems where on collections and on instances the developer can tell what EdmType is represented by the contents. Several places in the code are based on the raw CLR types without considering that instances might not directly map to a EDM type by their type. Just to name a few:
At the places where a EDM type is resolved for a CLR type (or vice versa) e.g. the
IEdmModel
should be asked to translate it to a EdmType. Currently a lot of this functionality is implemented in internal extension methods (mostly inEdmLibHelpers
) and can not be changed/extended. Also, where possible, rather the actual object should be used for the translation than its type loaded via GetType(). A customIEdmModel
implementation (or a special one provided by the framework) can then do the correct translation between CLR objects/types and EDM types.A EDM model construction could look like this:
For queryables/enumerables there could be a extension method which creates a "wrapper" IQueryable which annotates the original query with the edm types contained. This would allow polymorphic collections but also on strictly type collections the base type is defined.
That should give a first basic picture. A final implementation will likely need way more adjustments to ensure the mappings and object constructions work as expected everywhere. With this mapping in place also all other functionality ($filter, $select etc.) will work via the normal property aliasing.
The text was updated successfully, but these errors were encountered: