{"id":213,"date":"2014-07-23T20:22:00","date_gmt":"2014-07-23T20:22:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/odatateam\/2014\/07\/23\/tutorial-sample-using-unsigned-integers-in-odata\/"},"modified":"2020-01-07T04:47:31","modified_gmt":"2020-01-07T11:47:31","slug":"tutorial-sample-using-unsigned-integers-in-odata","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/odata\/tutorial-sample-using-unsigned-integers-in-odata\/","title":{"rendered":"[Tutorial &amp; Sample] Using Unsigned Integers in OData"},"content":{"rendered":"<p style=\"text-align: left;\" align=\"center\"><span style=\"font-size: 12px;\">Unsigned integers can be useful in many ways, such as representing data sizes, resource handles <\/span><span style=\"font-size: 12px;\">and so on. Though OData V4 only supports signed integer natively, the protocol offers a flexible way called type definition to allow users to \u2018define\u2019 unsigned integer types themselves.<\/span><\/p>\n<p>As an example, we know that any<em> UInt16<\/em> integer can be represented by the primitive type <em>Edm.Int32<\/em>. Thus by type definition, we can define a new type named <em>MyNamespace.UInt16<\/em> whose underlying type is <em>Edm.Int32<\/em>. By doing so, we can store and serialize <em>UInt16<\/em> integers as <em>Edm.Int32<\/em> ones. There are three advantages of leveraging type definition here:<\/p>\n<p>(1)\u00a0\u00a0\u00a0 Prevent breaking clients who conform to the protocol (to recognize type definitions) but are unaware of unsigned integer types.<\/p>\n<p>(2)\u00a0\u00a0\u00a0 Give the underlying type a different name that is meaningful to the context.<\/p>\n<p>(3)\u00a0\u00a0\u00a0 Enable the flexibility to change the underlying type without breaking the \u2018unsigned integer\u2019 type semantics.<\/p>\n<p>From version 6.5.0, our OData library starts to provide built-in support for unsigned integer types (including <em>UInt16<\/em>, <em>UInt32<\/em> and <em>UInt64<\/em> for now) as a protocol extension. Generally a user would have to write very little code to gain a workable model with default implementation of unsigned integers. Meanwhile, the library is flexible that users are allowed to use their customized implementation as well.<\/p>\n<h2>Introducing Type Definition<\/h2>\n<p>Before diving into unsigned integers, let\u2019s first take a look at how to define and use type definitions in OData. Suppose we want to define a new type <em>Height<\/em> whose underlying type is <em>Edm.Double<\/em> and use it to define a property <em>MyHeight<\/em> in an entity type <em>Person <\/em>(it is the same for complex type).<\/p>\n<p>We can write the following CSDL for the model:<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/lewischeng-ms\/ff1d234b190efeecffcb.js?file=typedef-1.xml\"><\/script><\/p>\n<p>Or write the equivalent code in C#:<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/lewischeng-ms\/ff1d234b190efeecffcb.js?file=typedef-2.cs\"><\/script><\/p>\n<p>The following code demonstrates the creation of a <em>Person <\/em>entry:<\/p>\n<p>You can serialize\/deserialize the above entry to\/from payload with the above model as usual.<\/p>\n<p>The underlying type of a type definition must be a primitive type rather than an entity type, a complex type, an enumeration type, or even a type definition. However, two type definitions with the same underlying type along with the underlying primitive type itself are treated assignable from (or equivalent to) each other so all the expressions below evaluate to true:<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/lewischeng-ms\/ff1d234b190efeecffcb.js?file=typedef-4.cs\"><\/script><\/p>\n<p>This means the three types are type-comparable and exchangeable to each other in model definition, serialization and deserialization. Take entry deserialization for example, you can post <em>Person <\/em>entities specifying the type of<em> MyHeight <\/em>as <em>SomeNamespace.Length <\/em>or <em>Edm.Double<\/em>, which should both work perfectly.<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/lewischeng-ms\/ff1d234b190efeecffcb.js?file=typedef-5.json\"><\/script><\/p>\n<h2>Using Unsigned Integers<\/h2>\n<p>Unsigned integers are supported based on type definition. Say if a user wants to use <strong><em>UInt32<\/em><\/strong> as property type in his model, a corresponding type definition should be added to the model so that a compliant client can recognize the <strong><em>UInt32<\/em> <\/strong>type.<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/lewischeng-ms\/ff1d234b190efeecffcb.js?file=uint-1.xml\"><\/script><\/p>\n<p>This is done automatically if using the default implementation of unsigned integers of our library. Or you can add your own type definition if you want to override the underlying type.<\/p>\n<p>But this is just about model definition. The next thing to consider should be how to serialize\/deserialize entries with unsigned integers. Suppose we have the following <em>Employee<\/em>entry:<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/lewischeng-ms\/ff1d234b190efeecffcb.js?file=uint-2.cs\"><\/script><\/p>\n<p>Since OData V4 only supports signed integers, we have to convert <em>UInt32<\/em> value <strong>to<\/strong> the underlying type <em>Int64<\/em> known to the protocol before serializing it to the payload. Thus we may obtain an entry payload like:<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/lewischeng-ms\/ff1d234b190efeecffcb.js?file=uint-3.json\"><\/script><\/p>\n<p>If we want to deserialize the above payload to an <em>Employee<\/em> entry, we first get an <em>Int64<\/em> value of <em>StockQuantity<\/em> directly from the payload. Then we need to convert the value <strong>from<\/strong> the underlying type <em>Int64<\/em> to <em>UInt32<\/em>.<\/p>\n<p>These two kinds of conversion are defined by the interface <em>IPrimitiveValueConverter<\/em> and its implementing classes:<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/lewischeng-ms\/ff1d234b190efeecffcb.js?file=uint-4.cs\"><\/script><\/p>\n<p>Each model has an internal dictionary that maps each type definition within the model to a primitive value converter, which converts value between the user type (e.g., <em>UInt32<\/em> here) and its underlying type (e.g.,\u00a0<em>Int64<\/em> here). The library also offers a <em>DefaultPrimitiveValueConverter<\/em> used to handle the default conversions of unsigned integers. If a type definition is not associated with a converter in the model, the library uses the internal<em> PassThroughPrimitiveValueConverter<\/em> to directly pass though the value without conversion.<\/p>\n<h3>Default Implementation<\/h3>\n<p>The default implementation of unsigned integers enables users to write the least code to support unsigned integers in their models. It consists of two parts: (1).default type definitions of unsigned integer types; (2).default primitive value converter for unsigned integers.<\/p>\n<p>For the first part, the default type definitions are listed below:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"288\">\n<p style=\"text-align: left;\"><strong>Type Definition Name<\/strong><\/p>\n<\/td>\n<td style=\"text-align: left;\" valign=\"top\" width=\"288\"><strong>Default Underlying Type<\/strong><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"288\"><strong>SomeNamspace.UInt16<\/strong><\/td>\n<td valign=\"top\" width=\"288\">Edm.Int32<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"288\"><strong>SomeNamspace.UInt32<\/strong><\/td>\n<td valign=\"top\" width=\"288\">Edm.Int64<\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\" valign=\"top\" width=\"288\"><strong>SomeNamspace.UInt64<\/strong><\/td>\n<td valign=\"top\" width=\"288\">\n<p style=\"text-align: left;\">Edm.Decimal<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>For the second part, the default conversions of unsigned integers are listed below:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"192\"><strong>User Type<\/strong><\/td>\n<td valign=\"top\" width=\"192\"><strong>Underlying Type<\/strong><\/td>\n<td valign=\"top\" width=\"192\"><strong>Type Definition<\/strong><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"192\"><strong>System.UInt16<\/strong><\/td>\n<td valign=\"top\" width=\"192\">System.Int32<\/td>\n<td valign=\"top\" width=\"192\">SomeNamespace.UInt16<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"192\"><strong>System.UInt32<\/strong><\/td>\n<td valign=\"top\" width=\"192\">System.Int64<\/td>\n<td valign=\"top\" width=\"192\">SomeNamespace.UInt32<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"192\"><strong>System.UInt64<\/strong><\/td>\n<td valign=\"top\" width=\"192\">System.Decimal<\/td>\n<td valign=\"top\" width=\"192\">SomeNamespace.UInt64<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The following example illustrates the usage of the default implementation. Suppose we want to create an entity type <em>Product <\/em>with <em>Quantity<\/em> of <em>UInt16<\/em>, <em>StockQuantity<\/em> of <em>UInt32<\/em> and <em>LifeTimeSeconds<\/em> of <em>UInt64<\/em>, we can simply write the following code:<\/p>\n<p>You can then serialize\/deserialize the entry with the model as usual and the default primitive value converter will automatically handle all the underlying conversions.<\/p>\n<h3>User Customization<\/h3>\n<p>In case you want to override the underlying type and the conversions of an unsigned integer type, you can define your own type definition and primitive value converter.<\/p>\n<p>Say if you want to use <em>Edm.String<\/em> as the underlying type of <em>UInt64<\/em>, you first need to create a new type definition along with the types that need it.<\/p>\n<p>Secondly define a custom converter between <em>UInt64<\/em> and <em>String<\/em>.<\/p>\n<p>Thirdly associate a <em>MyConverter<\/em> instance with that type definition in the model.<\/p>\n<p>Then you will be able to serialize an entry with UInt64:<\/p>\n<p>You may get the payload like:<\/p>\n<p>If you want to get the corresponding converter for a type definition, you can do as follows:<\/p>\n<h3>Querying Unsigned Integer Properties<\/h3>\n<p>You can query unsigned integer properties just as querying other primitive ones. Regarding the above sample, the following queries are supported:<\/p>\n<p>For query options, support of custom unsigned integer types is NOT guaranteed. Currently <strong>only unsigned integers of default implementation<\/strong> are well supported. Here are a few examples:<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Unsigned integers can be useful in many ways, such as representing data sizes, resource handles and so on. Though OData V4 only supports signed integer natively, the protocol offers a flexible way called type definition to allow users to \u2018define\u2019 unsigned integer types themselves. As an example, we know that any UInt16 integer can be [&hellip;]<\/p>\n","protected":false},"author":521,"featured_media":3253,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-213","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-odata"],"acf":[],"blog_post_summary":"<p>Unsigned integers can be useful in many ways, such as representing data sizes, resource handles and so on. Though OData V4 only supports signed integer natively, the protocol offers a flexible way called type definition to allow users to \u2018define\u2019 unsigned integer types themselves. As an example, we know that any UInt16 integer can be [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/213","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/users\/521"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/comments?post=213"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/213\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media\/3253"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media?parent=213"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/categories?post=213"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/tags?post=213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}