{"id":409,"date":"2008-07-30T00:00:00","date_gmt":"2008-07-30T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/creating-service-orientated-data-access-layers\/"},"modified":"2021-05-17T18:36:46","modified_gmt":"2021-05-17T18:36:46","slug":"creating-service-orientated-data-access-layers","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/creating-service-orientated-data-access-layers\/","title":{"rendered":"Creating Service-Orientated Data-Access Layers"},"content":{"rendered":"<div id=\"pretty\">\n<h2>Using ADO.NET Data Services<\/h2>\n<div class=\"contents\">\n<h2>Contents<\/h2>\n<ul>\n<li><a href=\"#first\">Introduction<\/a><\/li>\n<li><a href=\"#second\">Creating ADO.NET Data Services<\/a><\/li>\n<li><a href=\"#third\">Querying Data <\/a>\n<ul>\n<li><a href=\"#fourth\">Query Interceptors<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#fifth\">Manipulating Data<\/a>\n<ul>\n<li><a href=\"#sixth\">Change Interceptors<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#seventh\">Extending ADO.NET Data Services<\/a>\n<ul>\n<li><a href=\"#eighth\">Service Operations<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#ninth\">Consuming ADO.NET Data Services<\/a><\/li>\n<li><a href=\"#tenth\">Exposing in-memory data<\/a><\/li>\n<li><a href=\"#eleventh\">Conclusion<\/a><\/li>\n<\/ul>\n<\/div>\n<h3 id=\"first\">Introduction<\/h3>\n<p>ADO.NET Data Services allows you to expose data as entities over a service. This provides an elegant way of using a &#8216;Linq to SQL&#8217; model or an &#8216;ADO.NET Entity&#8217; model over a WCF service layer. The applications accessing the WCF Service layer to work with the data can be any application that can send HTTP requests.. This article introduces ADO.NET Data Services and explains how to create service-oriented data access layers that can be accessed over HTTP. This article is based on ADO.NET Data Services that ships with Visual Studio.NET 2008 Service Pack 1.<\/p>\n<p>ADO.NET Data Services provides access to the data model and allows you to perform CRUD operations over REST based services. REST stands for REpresentational State Transfer (REST). This allows any entity from the data model to be accessed by a URI. The type of CRUD operation to perform on an entity will depend on the HTTP verb used to access the entity. For example the HTTP GET operation is used to retrieve an entity, POST to create an entity, PUT to update an entity and DELETE to delete an entity.<\/p>\n<p>ADO.NET Data Services enables you to work with the data model through HTTP and by changing the request content-type allows you to serve the data in multiple formats. At the time of writing ADO.NET Data Services supports ATOM (ATOM is a XML based syndication format for web feeds) and <a href=\"http:\/\/www.simple-talk.com\/sql\/t-sql-programming\/json-and-other-data-serialization-languages\/\">JSON (JavaScript Object Notation) formats.<\/a><\/p>\n<p>ADO.NET Data Services opens up possibilities to work with data in new ways and provides many advantages. It works very well as a service application for Silverlight applications and AJAX web applications, and allows you to send requests to retrieve data in the required format without refreshing the web page. It also works with Adobe AIR applications or java client applications or just about any type of applications that can make HTTP requests to the service layer. By using both ADO.NET Entity Framework and ADO.NET Data Services, we can create service oriented data access layers providing data from the database to these different applications. Because of the REST model, the dependencies on the actual technology implementing the service or database specific implementations are shielded from the application accessing the service.<\/p>\n<h3 id=\"second\">Creating ADO.NET Data Services<\/h3>\n<p>Let us create a simple ADO.NET Entity Data Model named Contoso inside an ASP.NET web application. The Contoso ADO.NET Entity Data Model has the following entities generated from the database. I will not be going into ADO.NET Entity Framework and for more details you can check <a href=\"http:\/\/www.simple-talk.com\/dotnet\/.net-framework\/entity-framework-the-cribsheet\/\">the cribsheet on ADO.NET Entity Framework.<\/a><\/p>\n<p class=\"figure\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/imported\/538-image001.jpg\" alt=\"538-image001.jpg\" width=\"581\" height=\"290\" \/><\/p>\n<p>To expose the above data model using ADO.NET Data Services, let us add an ADO.NET Data Service to our project and name it as <b>ContosoDal.svc<\/b>. We need to alter the code behind for the<b> ContosoDal.svc<\/b> to work with the Contoso ADO.NET Entity Data Model we created and then specify the entity sets in our model that are accessed through the ADO.NET Data Services. For example to allow access to both our entities in the data model we can alter the code behind as follows<\/p>\n<p class=\"codelabel\">C# Code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">public class ContosoDal : \r\n\u00a0\u00a0\u00a0 DataService&lt;ContosoModel.ContosoEntities&gt;\r\n{\r\n\u00a0\u00a0\u00a0 public static void InitializeService(\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 IDataServiceConfiguration config)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 config.SetEntitySetAccessRule(\"*\", EntitySetRights.All);\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n\u00a0\r\n<\/pre>\n<p>The <b>ContosoModel.ContosoEntities<\/b> refers to the <b>ObjectContext<\/b> type for the ADO.NET Entity Data Model that we created. The &#8220;*&#8221; specifies that we want to include all the entities in our data model, and the <b>EntitySetRights<\/b> enumeration controls the type of access we are allowing for our entity sets. We can also set the <b>EntitySetRights<\/b> for each entity set individually and restrict the type of access we want to allow to the entity set. Now if we navigate to the <b>ContosoDal.svc<\/b> by setting it as the start up page, we should see the list of entity sets from the ADO.NET Data Service retrieved as an ATOM feed<\/p>\n<h3 id=\"third\">Querying Data<\/h3>\n<p>You can query data by executing HTTP GET operations over simple URIs. For example, to list out all the customer entity instances from the Customers entity set we can append the entity set name to the base URI for the <b>ContosoDal.svc<\/b><\/p>\n<p>http:\/\/localhost:8885\/ContosoDal.svc\/Customers<\/p>\n<p>Accessing the above URI will list out all the Customer entity instances in the Customers entity set. To just display details about a single Customer entity, I can pass the primary key value in the URI as follows:<\/p>\n<p>http:\/\/localhost:8885\/ContosoDal.svc\/Customers(1)<\/p>\n<p>The above URI based query will list out the details of the Customer entity instance with the primary key column ID set to 1. If I want to display just a property value of an entity, I can append the name of the property to the URI<\/p>\n<p>&nbsp;<\/p>\n<p>http:\/\/localhost:8885\/ContosoDal.svc\/Customers(1)\/Country<\/p>\n<p>The above URI displays just the Country property value for the Customer entity instance with the primary key set to 1. Similarly we can traverse through associations as well. For example the following URI displays the Order entity instances for the Customer entity that has the primary key set to 1<\/p>\n<p>http:\/\/localhost:8885\/ContosoDal.svc\/Customers(1)\/Orders<\/p>\n<p>We can also sort, filter and page the results when querying entity sets. For example the following URI return all the Customer entity instances where the Country property is set to UK<\/p>\n<p>http:\/\/localhost:8885\/ContosoDal.svc\/Customers?$filter=Country eq &#8216;UK&#8217;<\/p>\n<p>We can add a <b>$skip, $top <\/b>and <b>$orderby <\/b>query parameters to implement paging and sorting<\/p>\n<p>http:\/\/localhost:8885\/ContosoDal.svc\/Customers?$filter=Country eq &#8216;UK&#8217;$orderby=City desc$skip=10$top=10<\/p>\n<p>The above query filters for Customer entity instances from the UK and sorts the result by the descending order of the City property and skips the first 10 records and retrieves the next 10 results<\/p>\n<h5 id=\"fourth\">Query Interceptors<\/h5>\n<p>Query interceptors are useful when you want to run your own custom methods when queries are executed against your entity sets. For example let us assume you want to restrict the results in the query based on the current logged in users&#8217; credentials, we can write a query interceptor to intercept the query for an entity set and restrict the returned results. Since the query interceptor is part of the ADO.NET Data Service, the client will not be aware that an interceptor was used on the results.<\/p>\n<p>To understand query interceptors, let us do a very simple implementation. Let us create a query interceptor that returns only Customer entity instances from UK when someone queries our Customers entity set.<\/p>\n<p class=\"codelabel\">C# Code<\/p>\n<pre class=\"lang:c# theme:vs2012\">[QueryInterceptor(\"Customers\")]\r\npublic Expression&lt;Func&lt;Customer, bool&gt;&gt; \r\n\u00a0\u00a0\u00a0 CheckIfCountryValid()\r\n{\r\n\u00a0\u00a0\u00a0 return c =&gt; c.Country == \"UK\";\r\n}\r\n<\/pre>\n<p>We can define the above method inside our data service class <b>ContosoDal. <\/b>A query interceptor will not accept any arguments and will return an expression that accepts a Customer object and returns a Boolean value indicating on what condition the instance should be included in the result. We also adorn the method with the<b> QueryInterceptor<\/b> attribute indicating which entity set our query interceptor works on. Now when we query the Customers entity set, we will get only Customer entity instances where the Country property value is set to UK.<\/p>\n<h3 id=\"fifth\">Manipulating Data<\/h3>\n<p>We can manipulate data by making use of the HTTP verbs <b>POST<\/b>, <b>PUT<\/b> and <b>DELETE <\/b>for inserts, updates and deletes respectively. We can do these operations by making web requests using the WebRequest class to do the respective operations. But a simpler way is to create clients as detailed in the Consuming ADO.NET Data Services section in this article. This shields the HTTP verbs and provides a simpler model in manipulating and retrieving data.<\/p>\n<h5 id=\"sixth\">Change Interceptors<\/h5>\n<p>Similar to query interceptors, change interceptors execute code during inserts, updates and deletes. We can define a change interceptor to perform any validations etc during inserts, updates and deletes. To create a change interceptor, we can define a method that accepts an entity instance and the <b>UpdateOperations<\/b> enumeration.\u00a0 The <b>UpdateOperations<\/b> enumeration can be used within the method body to restrict the change interceptor to execute only for one or more specific operations such as insert, update or delete.\u00a0 For example the following change interceptor assigns the Country property as UK during inserts, if there is no value set for the Country property.<\/p>\n<p class=\"codelabel\">C# Code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">[ChangeInterceptor(\"Customers\")]\r\npublic void AssignDefaultCountry(\r\n\u00a0\u00a0\u00a0 Customer c, UpdateOperations operation)\r\n{\r\n\u00a0\u00a0\u00a0 if (operation == UpdateOperations.Add)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (c.Country.Trim().Length == 0)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 c.Country = \"UK\";\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n<\/pre>\n<p>Similar to the query interceptor, we need to adorn the method with the <b>ChangeInterceptor<\/b> attribute to specify the entity set against which the change interceptor would be executed.<\/p>\n<h3 id=\"seventh\">Extending ADO.NET Data Services<\/h3>\n<p>You can extend ADO.NET Data Services by providing your own methods called as service operations to your data services. Service operations enables you to write your own custom logic that can access stored procedures mapped in the ADO.NET Entity Data Model etc.<\/p>\n<h5 id=\"eighth\">Service Operations<\/h5>\n<p class=\"codelabel\">C# Code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">[WebGet]\r\npublic IQueryable&lt;Customer&gt; \r\n\u00a0\u00a0\u00a0 GetCustomersFromCountry(string country)\r\n{\r\n\u00a0\u00a0\u00a0 IQueryable&lt;Customer&gt; query = \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 from c in this.CurrentDataSource.Customers\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 where c.Country == country\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 select c;\r\n\u00a0\u00a0\u00a0 return query;\r\n}\r\n<\/pre>\n<p>The above will create a method that can be accessed by sending a GET request. One additional thing we must do is enable access to the service operation by marking it in the<b> InitializeService<\/b> method of our ADO.NET Data Service class<\/p>\n<p class=\"codelabel\">C# Code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">public static void InitializeService(\r\n\u00a0\u00a0\u00a0 IDataServiceConfiguration config)\r\n{\r\n\u00a0\u00a0\u00a0 config.SetEntitySetAccessRule(\"*\", EntitySetRights.All);\r\n\u00a0\u00a0\u00a0 config.SetServiceOperationAccessRule(\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"GetCustomersFromCountry\", ServiceOperationRights.All);\r\n}\r\n<\/pre>\n<h3 id=\"ninth\">Consuming ADO.NET Data Services<\/h3>\n<p>We can consume ADO.NET Data Services by creating proxy classes based on the URI. Visual Studio.NET 2008 SP1 ships a command line tool named DataSvcUtil. This command line tool can be used to generate the proxy classes to consume the ADO.NET Data Services. For example the following command generates a class file named proxy.cs based on the ADO.NET Data Services available at the URI http:\/\/localhost:8885\/ContosoDal.svc.<\/p>\n<pre>DataSvcUtil \/out:\"proxy.cs\" \/uri:\" http:\/\/localhost:8885\/ContosoDal.svc\"\r\n<\/pre>\n<p>We can include the generated proxy.cs in our client application and use the code in the proxy to make HTTP calls to the ADO.NET Data Service. For example the following code retrieves the list of Customer entity instances:<\/p>\n<p class=\"codelabel\">C# Code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">Uri uri = new Uri(\"http:\/\/localhost:8885\/ContosoDal.svc\");\r\nContosoEntities entities = new ContosoEntities(uri);\r\nList&lt;Customer&gt; customers = entities.Customers.ToList();\r\n<\/pre>\n<p>The ContosoEntities class is the data context and can be used to communicate with our data service. The queries we write in will change the URI to send to the data service.\u00a0 For example the above code will send a GET request to the URI http:\/\/localhost:8885\/ContosoDal.svc\/Customers.<\/p>\n<p>The simplest way to see the queries being executed is to create a handler for the SendingRequest event of the ContosoEntities data context. So let us go ahead and create a handler to display the URI in the console. Let us also modify the code to run a Linq query on the Customers entity set.<\/p>\n<p class=\"codelabel\">C# Code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">Uri uri = new Uri(\"http:\/\/localhost:8885\/ContosoDal.svc\");\r\nContosoEntities entities = new ContosoEntities(uri);\r\nentities.SendingRequest +=\r\n\u00a0\u00a0\u00a0 (object obj, SendingRequestEventArgs args) =&gt; \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine(\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 args.Request.RequestUri.ToString());\r\nList&lt;Customer&gt; customers = (from c in entities.Customers\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 where c.Country == \"UK\"\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 select c).ToList();\r\n<\/pre>\n<p>When you execute the above code it will display the URI&#8230; <br \/>\nhttp:\/\/localhost:8885\/ContosoDal.svc\/Customers()?$filter=Country eq &#8216;UK&#8217;<br \/>\n&#8230; in the console. So any linq query you write prepares the appropriate URI to send the GET request to.<\/p>\n<p>We can also do inserts, updates and deletes by using the data context object. For example the following code shows inserting a new Customer entity<\/p>\n<p class=\"codelabel\">C# Code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">Uri uri = new Uri(\"http:\/\/localhost:8885\/ContosoDal.svc\");\r\nContosoEntities entities = new ContosoEntities(uri);\r\nCustomer c = new Customer();\r\nc.ID = 4;\r\nc.Name = \"Customer D\";\r\nc.City = \"London\";\r\nc.Country = \"UK\";\r\nentities.AddToCustomers(c);\r\nentities.SaveChanges();\r\n<\/pre>\n<p>We can also execute our service operations by using our data context object.<\/p>\n<p class=\"codelabel\">C# Code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">Uri uri = new Uri(\"http:\/\/localhost:8885\/ContosoDal.svc\");\r\nContosoEntities entities = new ContosoEntities(uri);\r\nUri newUri = new Uri(uri.AbsoluteUri+\"\/GetCustomersFromCountry?country='UK'\");\r\nIEnumerable&lt;Customer&gt; customers = entities.Execute&lt;Customer&gt;(newUri);\r\n<\/pre>\n<p>The above code calls the service operation named GetCustomerFromCountry by passing the value &#8220;UK&#8221; as a parameter.<\/p>\n<p>Another type of client that is very suitable for ADO.NET Data Services is AJAX based clients. The ability to send a request to the ADO.NET Data Service requesting for data in JSON format, makes it a good technology to do server side operations in AJAX scenarios. There is a JavaScript library in codeplex available at <a href=\"http:\/\/www.codeplex.com\/aspnet\/Release\/ProjectReleases.aspx?ReleaseId=13357\">http:\/\/www.codeplex.com\/aspnet\/Release\/ProjectReleases.aspx?ReleaseId=13357<\/a>\u00a0 that can be used to make calls to ADO.NET Data Services. Once you add a reference to the downloaded JavaScript library, you can start writing JavaScript code for AJAX scenarios. For example the following JavaScript code queries for Customer entity instances that have the Country property set to UK.<\/p>\n<p class=\"codelabel\">JavaScript Code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">function doQuery() {\r\n\u00a0\u00a0\u00a0 var proxy = new Sys.Data.DataService(\"\/ContosoDal.svc\");\r\n\u00a0\u00a0\u00a0 proxy.query(\"Customers?$filter=Country eq 'UK'\", onSuccess);\r\n}\r\n\u00a0\r\nfunction onSuccess(res) {\r\n\u00a0\u00a0\u00a0 \/\/Process query results\r\n}\r\n<\/pre>\n<p>The above JavaScript function doQuery executes the GET request on the URI passed to the query method call of the DataService object.\u00a0 Then it will raise the callback function onSuccess on successful execution. Within the onSuccess function the res variable will have the query results, in this instance an array of Customer objects. Similarly we can do inserts, updates and delete also using the DataService object.<\/p>\n<h3 id=\"tenth\">Exposing in-memory data<\/h3>\n<p>Data doesn&#8217;t necessarily mean database. ADO.NET Data Services is very extensible and can work with in-memory data (such as a list of objects) as well as data from databases.<\/p>\n<p>For example I can create the following class:<\/p>\n<p class=\"codelabel\">C# Code:<\/p>\n<pre class=\"lang:c# theme:vs2012\">public class Customer\r\n{\r\n\u00a0\u00a0\u00a0 public int ID { get; set; }\r\n\u00a0\u00a0\u00a0 public string Name { get; set; }\r\n\u00a0\u00a0\u00a0 public string Company { get; set; }\r\n}\r\n\u00a0\r\nTo expose a list of objects created from the above class, I can create a container that returns a list of data as Queryable generic collection:\r\nC# Code:\r\npublic class CustomerContainer\r\n{\r\n\u00a0\u00a0\u00a0 private static List&lt;Customer&gt; customers = new List&lt;Customer&gt;();\r\n\u00a0\u00a0\u00a0 private static CustomerContainer()\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 customers.Add(new Customer() { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ID = 1, Name = \"Customer A\", Company = \"MS\" });\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/Add other Customer objects\r\n\u00a0\u00a0\u00a0 }\r\n\u00a0\r\n\u00a0\u00a0\u00a0 public IQueryable&lt;Customer&gt; Customers\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 get\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return customers.AsQueryable();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n<\/pre>\n<p>Once I add an ADO.NET Data Service to my project I can set the CustomerContainer as the DataService type and set the Customers property as the entity set to be exposed.<\/p>\n<p class=\"codelabel\">C# Code<\/p>\n<pre class=\"lang:c# theme:vs2012\">public class ContosoCustomDal : \r\n\u00a0\u00a0\u00a0 DataService&lt;CustomerContainer&gt;\r\n{\r\n\u00a0\u00a0\u00a0 public static void InitializeService(\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 IDataServiceConfiguration config)\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 config.SetEntitySetAccessRule(\"Customers\", EntitySetRights.AllRead);\r\n\u00a0\u00a0\u00a0 }\r\n}\r\n<\/pre>\n<h3 id=\"eleventh\">Conclusion<\/h3>\n<p>ADO.NET Data Services is a solution that enables you to expose a data model over a REST based service. This opens up a whole lot of possibilities to access data since the client application can access data by just sending a GET request to an URI and specify the response data format. By using the other HTTP methods such as PUT, POST and DELETE, we can modify the data as well. Since this represents the way the web works with resources, it fits naturally to web applications accessing data as resources.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The ADO.Net Data Services framework enables you to provide data services to Web applications that are simple to integrate with them. The data services use URIs to point to pieces of data, and use standards such as JSON and XML to transfer that data. ADO.NET Data Services uses the Entity Framework,&nbsp; which allows an easy translation from a Database layer based on Stored procedures, to an object-orientated Application layer. It all seems surprisingly sensible. Prasanna explains all, as usual.&hellip;<\/p>\n","protected":false},"author":124595,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,4229,4883,4168,4880,4217],"coauthors":[11327],"class_list":["post-409","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-net-framework","tag-net-home","tag-database","tag-json","tag-xml"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/409","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/124595"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=409"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/409\/revisions"}],"predecessor-version":[{"id":73553,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/409\/revisions\/73553"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=409"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=409"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=409"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=409"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}