Enumeration is a very common data type in various data models. Enumeration types are useful means to represent data that needs to support certain programmatic options (such as the ability to detect one or more options are selected). OData v4 now supports Enumeration types, along with Primitive types, Complex types, and Entity types. And we expect there will be heavy usage of them.
Let’s look at an example. Suppose we have an entity type called Product, and we want to have a property member that stores the color of the product. We could use a string type property, but an enumeration type property would look better. We can define an enumeration type Color, and it contains members like Red, Green, Blue, etc. In Product definition we can define a member property called PackageColor, whose type is Color. Now we can assign color values to PackageColor. To get all the products that are in Green color, we can send a request like “/svc/Products?$filter=PackageColor eq Namespace.Color’Green’”.
An enumeration type can be defined with “IsFlags=true”, meaning that the members can be combined using bitwise; otherwise the members are intended to be exclusive. The Color type in the example above is defined with “IsFlags=false”, as we don’t want its members to be combined (we don’t allow a color to be both green and blue). Here another example is an enumeration type called AccessLevel, which indicates the rights on some resource. AccessLevel has some members Like: None, Read, Write, Execute. In Product type we have another property named UserAccess which is of AccessLevel type. We can assign combined values to UserAccess, such as “Read, Write”. And if we want to get all the products that we have Read and Write access to, we can send a query like “/svc/Products?$filter=UserAccess has Namespace.Color’Read, Write’”. The “has” operator is evaluated in a bitwise way. That means UserAccess may contain more bits than the value on the right of the operator.
How to use Enumeration types in your OData service? The following part will give the elaborated steps, as well as some code snippets to help you understand. You can get the complete sample code here.
On server side, you need to first build an EDM model that supports your scenario with enumeration types. With the model ready, your service needs to respond to client requests by writing the correct payload which may have enumeration type values in it. The second step is called serialization. Let’s look at the details.
1. Build the EdmModel.
To use Enum type, you need to first define your Enum types in EdmModel. The enum type can be defined with "IsFlags=true" or “IsFlags=false”. The absence of the IsFlags attribute implies the default behavior: the same as "IsFlags=false".
The following code defines two Enum types: Color and AccessLevel, and an entity type Product which has two properties UserAccess and PackageColor, of type AccessLevel and Color respectively.
In $metadata, they look like:
2. Write payload
The next step to do is enable the service to write payloads that have enumeration type values. To write an entity that has enumeration type properties is not very different from the other entities. The only difference is at the entry creation stage. An Enum property has to be assigned an ODataEnumValue object which represents the Enum value. The code snippet below shows how to do it.
One thing to notice is, the ODataEnumValue is initialized with a string (“Green”,“Write”). The string can also be the underlying value like “1”, “4”.
Once our service is ready to support enumeration type values, we can build a client to consume the data. On client side, we need to read the payload and construct the property values. This process is called deserialization. Let’s look at how the client does it.
3. Read payload
The following code shows a client that reads an entry with Enum properties. At the end, packageColor.Value and userAccess.Value have the string values of the Enum properties. In our sample, packageColor.Value would be “Green”, and userAccess.Value would be “Write”.