{"id":423,"date":"2014-03-05T01:31:00","date_gmt":"2014-03-05T01:31:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/odatateam\/2014\/03\/05\/tutorial-sample-use-singleton-to-define-your-special-entity\/"},"modified":"2020-01-07T07:52:49","modified_gmt":"2020-01-07T14:52:49","slug":"tutorial-sample-use-singleton-to-define-your-special-entity","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/odata\/tutorial-sample-use-singleton-to-define-your-special-entity\/","title":{"rendered":"[Tutorial &amp; Sample] Use Singleton to define your special entity"},"content":{"rendered":"<p><span style=\"font-family: tahoma, arial, helvetica, sans-serif;\">Ever had a special entity where there can be only one of its kind, but bothered by having to define a one-element entity set for it? Ever wanted to request a special entity but bothered by needing to find out its key first? Use a singleton! Singleton is newly introduced in OData V4, to allow developers name such special entity, and it can be addressed directly by its name from the service root.<\/span><\/p>\n<p><span style=\"font-family: tahoma, arial, helvetica, sans-serif;\">Let&#8217;s think about a universal scenario which can benefit from singleton:<\/span><\/p>\n<p><span style=\"font-family: helvetica;\">We want to have a model to present the staff information of a company.<\/span><\/p>\n<p><span style=\"font-family: helvetica;\">So first, we define an EntityType named EmployeeType to represent the schema of an employee information, and accordingly define EmployeeSet (which is an EntitySet) to actually have the information of each employee.<\/span><\/p>\n<p><span style=\"font-family: helvetica;\">And second, we also want to have an entity to present the information of the company, like company name, logo, strategy etc. First step is to define an EntityType named CompanyType of cause, what about then, define an EntitySet named CompanySet? EntitySet means a collection of entities, but we only need one entity for company! Of cause you can have just one entity in the EntitySet, like what we did before V4. But to have one entity, you are forced to have a collection of entities! Singleton in V4 can release you from such an awkward situation.<\/span><\/p>\n<p><span style=\"font-family: helvetica;\">Defining company as a singleton at least have 2 advantages than defining company as an EntitySet:<\/span><\/p>\n<ul>\n<li><span style=\"font-family: helvetica;\">It is more straightforward in concept. Singleton is designed to present a special entity, just like company.<\/span><\/li>\n<li><span style=\"font-family: helvetica;\">You can directly access company from service root by querying &#8220;.svc\/Company&#8221;, without appending the CompanyID.<\/span><\/li>\n<\/ul>\n<h2>How to define and consume Singleton<\/h2>\n<p>Just little effort is needed for a service to support singleton. Basically, Singleton is quite similar with EntitySet, and the biggest difference of singleton and entityset is that when writing a singleton, we call CreateODataEntryWriter, rather than CreateODataFeedWriter for writing EntitySet. Same to call CreateODataEntryReader for reading a singleton.<\/p>\n<p>Following shows the simple steps to support singleton (<span style=\"text-decoration: underline;\"><a title=\"Sample Code\" href=\"https:\/\/odatasamples.codeplex.com\/SourceControl\/latest#Features\/Singleton\/\" target=\"_blank\" rel=\"noopener noreferrer\">Sample Code<\/a><\/span>).<\/p>\n<h3>Service side<\/h3>\n<p><strong>1. Define singleton in EDM model<\/strong><\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/luoyan0517\/9403673.js\"><\/script><\/p>\n<p><strong>2. Parse singleton segment in querying URI<\/strong><\/p>\n<p>When receiving a query uri, like &#8220;.svc\/Company&#8221;, service calls ODataUriParser to parse the uri, and in this case the last segment of the uri should be SingletonSegment.<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/luoyan0517\/9403693.js\"><\/script><\/p>\n<p><strong>3. Write a singleton<\/strong><\/p>\n<p>To write the response, service calls CreateODataEntryWriter to write the company info in json payload. To simply the example, we directly write the payload into a stream.<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/luoyan0517\/9403769.js\"><\/script><\/p>\n<h3>Client side<\/h3>\n<p>After sending the query &#8220;.svc\/Company&#8221;, client can receive a response from wire if everything works well. So client just need to call CreateODataEntryReader to read the singleton out.<\/p>\n<p>We have response in the stream in this example.<\/p>\n<h2>Singleton advanced features<\/h2>\n<p>The example above shows the simplest way to use a singleton, but there are some other advanced features of singleton:<\/p>\n<p><strong>1.<\/strong> <strong>Query singleton with query option<\/strong><\/p>\n<p>Singleton is an entity after all, so only <strong>$select and $expand<\/strong> are supported when singleton is the resource path.<\/p>\n<p>Sample Uri:<\/p>\n<p><span style=\"font-size: x-small;\"><em>.svc\/Company?$select=Name<\/em><\/span><\/p>\n<p><strong>2. Navigation<\/strong><\/p>\n<ul>\n<li>Singleton can have EntitySet, contained EntitySet or singleton as navigation property.<\/li>\n<li>Entityset can have singleton as navigation property<\/li>\n<\/ul>\n<p>Below is a code snippet to define navigation of singleton.<\/p>\n<p><script type=\"text\/javascript\" src=\"https:\/\/gist.github.com\/luoyan0517\/9404476.js\"><\/script><\/p>\n<p>Sample Uri:<\/p>\n<p><span style=\"font-size: x-small;\"><em>.svc\/Company\/Employees<\/em><\/span><\/p>\n<p><span style=\"font-size: x-small;\"><em>.svc\/Company?$expand=Employees<\/em><\/span><\/p>\n<p><span style=\"font-size: x-small;\"><em>.svc\/Employees(1)\/Company<\/em><\/span><\/p>\n<p><strong>3.<\/strong> <strong>Bound Action\/Function<\/strong><\/p>\n<p>Since bound action and function is defined on EntityType, singleton can inherited action and function from its defining EntityType.<\/p>\n<p>Sample Uri:<\/p>\n<p>GET <span style=\"font-size: x-small;\"><em>.svc\/Company\/NameSpace.GetEmployeesCount()<\/em><\/span> \/\/ GetEmployeesCount is a function<\/p>\n<p>POST <span style=\"font-size: x-small;\"><em>.svc\/Company\/NameSpace.IncreaseRevenue<\/em><\/span> with payload:\u00a0 <span style=\"font-family: Consolas; font-size: 8pt;\"><em><span style=\"font-family: helvetica;\">{&#8220;IncreaseValue&#8221;:20000}<\/span><\/em>\u00a0<span style=\"font-size: small; font-family: helvetica;\">\u00a0\/\/ IncreaseRevenue is an action<\/span><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ever had a special entity where there can be only one of its kind, but bothered by having to define a one-element entity set for it? Ever wanted to request a special entity but bothered by needing to find out its key first? Use a singleton! Singleton is newly introduced in OData V4, to allow [&hellip;]<\/p>\n","protected":false},"author":519,"featured_media":3253,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[48,54,68],"class_list":["post-423","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-odata","tag-odata","tag-odatalib","tag-singleton"],"acf":[],"blog_post_summary":"<p>Ever had a special entity where there can be only one of its kind, but bothered by having to define a one-element entity set for it? Ever wanted to request a special entity but bothered by needing to find out its key first? Use a singleton! Singleton is newly introduced in OData V4, to allow [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/423","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\/519"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/comments?post=423"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/423\/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=423"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/categories?post=423"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/tags?post=423"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}