{"id":643,"date":"2012-08-29T08:42:13","date_gmt":"2012-08-29T08:42:13","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/odatateam\/2012\/08\/29\/odata-101-using-the-notmapped-attribute-to-exclude-enum-properties\/"},"modified":"2012-08-29T08:42:13","modified_gmt":"2012-08-29T08:42:13","slug":"odata-101-using-the-notmapped-attribute-to-exclude-enum-properties","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/odata\/odata-101-using-the-notmapped-attribute-to-exclude-enum-properties\/","title":{"rendered":"OData 101: Using the [NotMapped] attribute to exclude Enum properties"},"content":{"rendered":"<p><strong>TL;DR:<\/strong> OData does not currently support enum types, and WCF Data Services throws an unclear exception when using the EF provider with a model that has an enum property. Mark the property with a <code class=\"prettyprint\">[NotMapped]<\/code> attribute to get around this limitation.<\/p>\n<p>In today\u2019s OData 101, we\u2019ll take a look at a problem you might run into if you have an Entity Framework provider and are using Entity Framework 5.0+.<\/p>\n<h3>The Problem<\/h3>\n<p>The problem lies in the fact that Entity Framework and WCF Data Services use a common format to describe the data model: the <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ee382825.aspx\" target=\"_blank\">Entity Data Model (EDM)<\/a>. In Entity Framework 5.0, the EF team made some modifications to MC-CSDL, the specification that codifies CSDL, the best-known serialization format for an EDM. Among other changes, the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/hh564254(v=prot.10)\" target=\"_blank\">EnumType element<\/a> was added to the specification. An EF 5.0 model in a project that targets .NET 4.5 will allow developers to add enum properties. However, WCF Data Services hasn\u2019t yet done the work to implement support for enum properties. (And the OData protocol doesn\u2019t have a mature understanding of how enums should be implemented yet; this is something we\u2019re working through with OASIS.)<\/p>\n<p>If you are trying to use an EF model that includes an enum property with WCF Data Services, you\u2019ll get the following error:<\/p>\n<blockquote>\n<p>The server encountered an error processing the request. The exception message is &#8216;Value cannot be null. Parameter name: propertyResourceType&#8217;. See server logs for more details. The exception stack trace is:<\/p>\n<p>at System.Data.Services.WebUtil.CheckArgumentNull[T](T value, String parameterName) at System.Data.Services.Providers.ResourceProperty..ctor(String name, ResourcePropertyKind kind, ResourceType propertyResourceType) at System.Data.Services.Providers.ObjectContextServiceProvider.PopulateMemberMetadata(ResourceType resourceType, IProviderMetadata workspace, IDictionary2 knownTypes, PrimitiveResourceTypeMap primitiveResourceTypeMap) at System.Data.Services.Providers.ObjectContextServiceProvider.PopulateMetadata(IDictionary2 knownTypes, IDictionary2 childTypes, IDictionary2 entitySets) at System.Data.Services.Providers.BaseServiceProvider.PopulateMetadata() at System.Data.Services.Providers.BaseServiceProvider.LoadMetadata() at System.Data.Services.DataService1.CreateMetadataAndQueryProviders(IDataServiceMetadataProvider&amp; metadataProviderInstance, IDataServiceQueryProvider&amp; queryProviderInstance, BaseServiceProvider&amp; builtInProvider, Object&amp; dataSourceInstance) at System.Data.Services.DataService1.CreateProvider() at System.Data.Services.DataService1.HandleRequest() at System.Data.Services.DataService1.ProcessRequestForMessage(Stream messageBody) at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]&amp; outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)<\/p>\n<\/blockquote>\n<p>Fortunately this error is reasonably easy to workaround.<\/p>\n<h3><\/h3>\n<h3>Workaround<\/h3>\n<p><strong>The first and most obvious workaround should be to consider removing the enum property from the EF model until WCF Data Services provides proper support for enums.<\/strong><\/p>\n<p>If that doesn\u2019t work because you need the enum in business logic, you can use the <code class=\"prettyprint\">[NotMapped]<\/code> attribute from <code class=\"prettyprint\">System.ComponentModel.DataAnnotations.Schema<\/code> to tell EF not to expose the property in EDM.<\/p>\n<p>For example, consider the following code:<\/p>\n<pre class=\"prettyprint linenums\">using System;\nusing System.ComponentModel.DataAnnotations.Schema;\n\nnamespace WcfDataServices101.UsingTheNotMappedAttribute\n{\n    public class AccessControlEntry\n    {\n        public int Id { get; set; }\n\n        \/\/ An Enum property cannot be mapped to an OData feed, so it must be\n        \/\/ explicitly excluded with the [NotMapped] attribute.\n        [NotMapped]\n        public FileRights FileRights { get; set; }\n\n        \/\/ This property provides a means to serialize the value of the FileRights\n        \/\/ property in an OData-compatible way.\n        public string Rights\n        {\n            get { return FileRights.ToString(); }\n            set { FileRights = (FileRights)Enum.Parse(typeof(FileRights), value); }\n        }\n    }\n\n    [Flags]\n    public enum FileRights\n    {\n        Read = 1,\n        Write = 2,\n        Create = 4,\n        Delete = 8\n    }\n}<\/pre>\n<p>In this example, we\u2019ve marked the enum property with the <code class=\"prettyprint\">[NotMapped]<\/code> attribute and have created a manual serialization property which will help to synchronize an OData-compatible value with the value of the enum property.<\/p>\n<h3>Implications<\/h3>\n<p>There are a few implications of this workaround:<\/p>\n<ol>\n<li>The <code class=\"prettyprint\">[NotMapped]<\/code> attribute also controls whether EF will try to create the value in the underlying data store. In this case, our table in SQL Server would have an nvarchar column called Rights that stores the value of the Rights property, but not an integer column that stores the value of FileRights. <\/li>\n<li>Since the FileRights column is not stored in the database, LINQ-to-Entities queries that use that value will not return the expected results. This is a non-issue if your EF model is only queried through the WCF Data Service.<\/li>\n<\/ol>\n<h3>Result<\/h3>\n<p>The result of this workaround is an enumeration property that can be used in business logic in the service code, for instance, in a <code class=\"prettyprint\">FunctionImport<\/code>. Since the <code class=\"prettyprint\">[NotMapped]<\/code> attribute prevents the enum value from serializing, your OData service will continue to operate as expected and you will be able to benefit from enumerated values.<\/p>\n<p>In the example above, there is an additional benefit of constraining the possible values for Rights to some combination of the values of the <code class=\"prettyprint\">FileRights<\/code> enum. An invalid value (e.g., Modify) would be rejected by the server since <code class=\"prettyprint\">Enum.Parse<\/code> will throw an <code class=\"prettyprint\">ArgumentException<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TL;DR: OData does not currently support enum types, and WCF Data Services throws an unclear exception when using the EF provider with a model that has an enum property. Mark the property with a [NotMapped] attribute to get around this limitation. In today\u2019s OData 101, we\u2019ll take a look at a problem you might run [&hellip;]<\/p>\n","protected":false},"author":512,"featured_media":3253,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[30,37,49,65,89],"class_list":["post-643","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-odata","tag-enums","tag-how-to","tag-odata-101","tag-samples","tag-workarounds"],"acf":[],"blog_post_summary":"<p>TL;DR: OData does not currently support enum types, and WCF Data Services throws an unclear exception when using the EF provider with a model that has an enum property. Mark the property with a [NotMapped] attribute to get around this limitation. In today\u2019s OData 101, we\u2019ll take a look at a problem you might run [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/643","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\/512"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/comments?post=643"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/643\/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=643"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/categories?post=643"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/tags?post=643"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}