<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>RunOfTheMillBlog : Data</title><link>http://blogs.msdn.com/ramkoth/archive/tags/Data/default.aspx</link><description>Tags: Data</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Service Boundaries, Business Services and Data</title><link>http://blogs.msdn.com/ramkoth/archive/2004/03/08/85802.aspx</link><pubDate>Tue, 09 Mar 2004 04:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:85802</guid><dc:creator>ramkoth</dc:creator><slash:comments>16</slash:comments><comments>http://blogs.msdn.com/ramkoth/comments/85802.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ramkoth/commentrss.aspx?PostID=85802</wfw:commentRss><description>&amp;nbsp;One of the core tenets of SOA is that the services have a clearly defined boundary. Services &lt;SPAN style="FONT-WEIGHT: bold"&gt;explicitly&lt;/SPAN&gt; choose to expose certain (business) functions outside the boundary. Another tenet of SOA is that a service - with in its boundary - owns, encapsulates and protect its private data. But, there are not too many guidelines out there that talks about what should be exposed and how the boundaries should be drawn. 
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Keep an eye on 'Data cohesion' when you are designing the service boundary. I will give you an example. A while back, I was involved in architecting a product that has many different modules - like sales, finance, inventory, CRM, billing etc. Our natural instinct was to define each of these modules as a 'Service'. So, we went ahead and defined a Sales service, CRM service, Finance service etc. We defined the entities that are required for each one of these apps and designed the database schema etc. Also, following SOA's design principles, we defined the contracts for the services and exposed different functionalities. Finally, we used web services as a implementation mechanism to expose the services. At the end of the day, we thought we had a pretty good design.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;But, things started falling apart the moment we started integrating different services. The main problem we faced was that the 'Customer' entity is required by all the systems. This entity can be updated by all the services. So, we had to implement a nasty 'merge replication' like infrastructure over web-services in order to keep the customer data in sync. To avoid building merge-replication infrastructure across service boundaries, we decided to remove the so called common entities (customer, product etc) and created a separate module or service for them - conveniently named common module. The idea here is that the common module provides services that abstracts the common entities and exposes operations for CRUD behavior (I know&amp;#8230;CRUD is a bad word). There is another way to do that as well. For each entity, designate a service as a owner (a.k.a., System of record). You can think of Common module as a system of record for the common entities. So, in theory, both the approaches are equivalent.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;So, we went down the path of building a common module (system of record)&amp;nbsp;for common entities. Things worked for a while, before we got into implementing a scenario that actually required a cross-join between product entity and a related entity owned by order management service. Mind you, this is really not a business intelligence scenario. This is a simple search screen that should go to database, do the search and show the results for end-user to pick an item. Performance will go down the tube, if you implement a cross-join between entities owned by different services.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;So, you have to build EII (Enterprise Information Integration) like solutions, which will most probably replicate related entities, so that joins can be done efficiently in database. And, we all know that building an EII solution is a costly affair.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;So, what is the solution? Here is a practical one. &lt;SPAN style="FONT-STYLE: italic"&gt;"Try to share the database between related services.&amp;#8220;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&lt;SPAN style="FONT-STYLE: italic"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;But, 'wait a minute', you may ask - 'you are saying something heretic. Services are not supposed to share data between them'. Well, you are right. But, remember the problems created by simply adhering to core tenets of services. One of the problem with the core tenet of services is that the boundary tenet doesn't talk about data, it only talks about what should or should not be exposed. Since it doesn't talk about data, it is very easy draw service boundaries that may create data related problems later on.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;If we still want to remain a purist, we have two choices: 1) re-interpret/relax service boundary rule 2) define a new type of service called business service. I believe option 2 is probably the best path.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Think of business service as a software system that automates one or more business capabilities. A business service may expose one or more services that correspond to each business capability. But, all those services share a logical data model. &lt;SPAN style="FONT-STYLE: italic"&gt;In other words, boundary is defined at the business service level and not at the individual service level.&lt;/SPAN&gt; This is an important lesson we learnt. &lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;For example, think of your favorite ERP system (SAP, Peoplesoft etc) as a business service that exposes one more services - one for HR management, one for Inventory, one for Order management, one for Accounting etc. But, they all share single logical data model. Ever wondered, why big ERP systems such as SAP have a single database that contains the tables required by all the modules? I tend to think this is the reason why they did it. But, I may be wrong. &lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;So, here is the summary of key practical learnings&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in; MARGIN-BOTTOM: 0in; MARGIN-LEFT: 0.5in; DIRECTION: ltr; unicode-bidi: embed" type=a&gt;
&lt;LI style="MARGIN-TOP: 0px; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; FONT-FAMILY: Verdana; mso-outline-level: 1" value=1&gt;Define boundary at the business service level. 
&lt;LI style="MARGIN-TOP: 0px; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; FONT-FAMILY: Verdana; mso-outline-level: 1" value=2&gt;Business service may contain one or more services, but share data. 
&lt;LI style="MARGIN-TOP: 0px; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; FONT-FAMILY: Verdana; mso-outline-level: 1" value=3&gt;If you have legacy systems that you have to integrate, then you can't do much. Business services and their boundaries have been defined for you. &lt;/LI&gt;&lt;/OL&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=85802" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ramkoth/archive/tags/Data/default.aspx">Data</category><category domain="http://blogs.msdn.com/ramkoth/archive/tags/SOA/default.aspx">SOA</category></item><item><title>Pagination and SQL</title><link>http://blogs.msdn.com/ramkoth/archive/2003/12/22/45056.aspx</link><pubDate>Mon, 22 Dec 2003 23:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:45056</guid><dc:creator>ramkoth</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/ramkoth/comments/45056.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ramkoth/commentrss.aspx?PostID=45056</wfw:commentRss><description>&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Almost all applications require end-users to search through information. Search results are often shown in some sort of list controls such as Grid, Listview etc. It is very often the case that the search results contain too many records to show in one page. In those cases, search results are shown one page after another, each page containing fixed number of records.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Various solutions have been tried by solution developers. They include creating temporary tables that contain the result set to caching the result set in middle-tier for faster access. There are pros and cons to each approach which I will not delving into.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;This article explains another way to do pagination. This mechanism leaves most of the work to RDBMS query execution engine. It works like this.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL style="MARGIN-TOP: 0in; MARGIN-BOTTOM: 0in; MARGIN-LEFT: 0.5in; DIRECTION: ltr; unicode-bidi: embed" type=a&gt;
&lt;LI style="MARGIN-TOP: 0px; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; FONT-FAMILY: Verdana; mso-outline-level: 1" value=1&gt;Presentation layer executes the initial search query based on user preferences. This query returns top &amp;lt;n&amp;gt; rows where n = pagesize.&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; FONT-FAMILY: Verdana; mso-outline-level: 1" value=2&gt;Presentation layer code then saves information about first row and last row fetched.&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; FONT-FAMILY: Verdana; mso-outline-level: 1" value=3&gt;When user triggers 'Previous' command, presentation layer goes back to SQL and fetches a page of matched records before the first row.&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; FONT-FAMILY: Verdana; mso-outline-level: 1" value=4&gt;When user triggers 'Next' command, PL goes back to SQL and fetches a page of matched records after the last row&lt;/LI&gt;&lt;/OL&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Here is an example. Let's take the example of Employees table in Northwind database. This table contains following fields (Data types are not included for brevity)&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;EmployeeId (PK), LastName, FirstName, Title, BirthDate and other fields.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Let's say that we want to search employees by last name. The result sets should be ordered by last name.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Here is the initial query. I am assuming the page size is 20.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Select Top 20 LastName, FirstName, Title&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;From Employees&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Where LastName like @searchpattern --passed as input&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Order By LastName&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;After executing this, presentation layer store the values for LastName from the first row and last row in its state. This will be used in the processing of Previous and Next commands.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Previous Query&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;When user wants to see the previous page, presentation layer sends a query to SQL that returns a page of matched records. Search predicate should be modified as follows&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Where Clause := &lt;SPAN style="FONT-STYLE: italic"&gt;LastName like @lastname and LastName &amp;lt; &amp;lt;Value of last name from the first row&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Now the query looks like this&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Select Top 20 LastName, FirstName, Title&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;From Employees&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Where LastName like @searchpattern and LastName &amp;lt; @lastnamefromfirstrow --passed as input&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Order By LastName&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Next query&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Processing 'Next' is very similar to previous. The search predicate would look like&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Where clause := &lt;SPAN style="FONT-STYLE: italic"&gt;LastName like @lastname and LastName &amp;gt; &amp;lt;Value of last name from the last row&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Select Top 20 LastName, FirstName, Title&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;From Employees&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Where LastName like @searchpattern and LastName &amp;gt; @lastnamefromlastrow --passed as input&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Order By LastName&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Are we done? Not quite. These queries will work only if the LastName is unique, which we all know is not the case. So what should we do?&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;In these cases, we should include additional fields that make each record in the result set&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;unique. For example, adding EmployeeId as part of projection would guarantee uniqueness of record in the result set and order the result sets based on LastName followed by EmployeeId.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Here are the modified queries&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Initial query&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Select Top 20 EmployeeId, LastName, FirstName, Title&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;From Employees&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Where LastName like @lastname --passed as input&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Order By LastName, EmployeeId&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Prev Query&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Select Top 20 LastName, FirstName, Title&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;From Employees&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Where LastName like @searchpattern and &lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;( (LastName &amp;lt; @lastnamefromfirstrow) or &lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;((LastName=@lastnamefromfirstrow) and (EmployeeId &amp;lt; @empidfromfirstrow))&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Order By LastName, EmployeeId&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;This makes sure that even if the LastName is not unique, the previous query returns correct results. Next query is very similar to previous query.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;You can see that the query gets complicated due to uniqueness issue. But, it is easy to come up with a general form to frame queries appropriately. Also, one should create appropriate indices to make sure that the performance doesn't suffer. Stored procedures can also be used for faster processing.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Issues with this approach&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Main issue with this approach is that there are certain scenarios where things get difficult. For example, if you want to go to LastPage, or page &amp;lt;n&amp;gt;, then you have to stroll through one page after another to go to the page. There are ways to optimize this, but it needs little bit of additional coding and of course, there is a definite perf cost associated with this. &lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;But if your scenarios support only Prev and Next primitives, then this would work just fine.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=45056" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ramkoth/archive/tags/Data/default.aspx">Data</category></item><item><title>OR Technologies discussion contd</title><link>http://blogs.msdn.com/ramkoth/archive/2003/12/22/45028.aspx</link><pubDate>Mon, 22 Dec 2003 17:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:45028</guid><dc:creator>ramkoth</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/ramkoth/comments/45028.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ramkoth/commentrss.aspx?PostID=45028</wfw:commentRss><description>&lt;P&gt;What a way to start a blog!!! Got slammed by many people for my cut-throat remarks on futility of current OR technologies. But, I love to have continued discussion on this subject. There is couple of things to start with&lt;/P&gt;
&lt;P&gt;a) My remarks are derived from interacting with many customers who tried many different OR implementations and got disillusioned with it. Some of them are due to really ugly implementations of the technology (like J2 CMP) to some of them just didn&amp;#8217;t really solve their business scenarios.&lt;/P&gt;
&lt;P&gt;b) My research involved looking at *some* OR technologies offered by top vendors and I didn&amp;#8217;t really spend time trying to evaluate *all* technologies, which would take very long amount of time. My guess would be that at least 1 out 3 competent app developers have built their own OR technology. Yours truly has built two of them in my former life.&lt;/P&gt;
&lt;P&gt;c) I am not against abstraction of relational data. My comments are focused on what should be the right abstraction. The OR technologies of today predominantly use Static types such as classes and attributes that maps to tables/views and columns respectively. This is the abstraction that I was arguing against and I strongly believe a more amorphous data structure such as record sets or XML is probably the right way to go about.&lt;/P&gt;
&lt;P&gt;d) I realized that I shouldn&amp;#8217;t have used the term &amp;#8216;Datasets&amp;#8217; as it has lot more baggage associated with it than a simple record set.&lt;/P&gt;
&lt;P&gt;Sure enough, some of you may have implemented some thing like Field Collections for more flexible query, as one comment describes it, but I am not sure how this is conceptually different from Record Set. In fact, we are on the same page here.&lt;/P&gt;
&lt;P&gt;Also, some of the comments imply that OR fits really well on CRUD like scenarios. Perhaps, you are building such a simple app (I can think of departmental app that has only few users wanting to do few things). Even in this case, I am not sure if OR is helpful as the devs need to go through the training to understand this or that OR technology, where as things such as ADO&lt;?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /&gt;&lt;st1:mswterms w:st="on"&gt;.NET&lt;/st1:mswterms&gt; datasets provide those functionality out of box.&lt;/P&gt;
&lt;P&gt;Other arguments are about de-coupling database schema from application developers. I can&amp;#8217;t agree with this more. But, it takes a leap of faith to arrive at a conclusion that the OR technologies are the better way to achieve this. I have worked with ERP vendors in the past, and I have seen them taking a different approach (IMO, more elegant approach) to solve this. They do the following&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN style="mso-list: Ignore"&gt;1)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;Define domain model for the application. Here they define business terms such as Customer ID, LastName, firstname, address etc. On top of that they define entities that maps to business concepts such as Customer, Employee etc. They store this information in a repository (usually called as dictionary).&lt;/P&gt;
&lt;P style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN style="mso-list: Ignore"&gt;2)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;Then they define some attributes for business terms for consistent usage. This may contain information such as syntax, data type etc. Then they finally define storage attributes such as column names that should be used etc. This is not very different from ER modeling. &lt;/P&gt;
&lt;P style="MARGIN-LEFT: 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN style="mso-list: Ignore"&gt;3)&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;Finally, they map entities to tables/views.&lt;/P&gt;
&lt;P&gt;So far, this is not conceptually different from OR meta-data (except that the OR technologies I know have no concept of business terms. They tend to work at the level of entities). Where it is different is that the application developers (like HRMS devs) use queries that uses terms from domain model to get the data from back-end. These queries go through a query layer that translates the business terms and entities to actual fields and tables in the back-end. Again, this query layer is an infrastructure component and app devs are abstracted from translation. The whole point here is that this mechanism allows application developers to define a view of an entity and allows to extract information about that view. &lt;/P&gt;
&lt;P&gt;So, what is the advantage of all this? I will give you a simple example. If somebody wants to change a column name for a business term called Customer&amp;#8217;s last name from Lname to Lastname, then there is *only one* place in the dictionary that needs to be changed. You don&amp;#8217;t have to go and change mapping for every entity. In the OR technologies that I have reviewed, I need to go and change the mapping for all the entities that include this attribute, which is not an optimal way to do this and is error prone. Not that OR meta-data can be extended to do this. &lt;/P&gt;
&lt;P&gt;Finally, there is always a question of customization/extensibility. This is especially a big problem for ISVs. Usually customization involves extending the pre-defined entity by adding few more fields, or changing an attribute of a field from mandatory to optional and vice versa. If I use static types such as classes and structs, then it would take huge amount of customization effort to change the structure of these types, add mapping information and deploy them. On the other hand, flexible data structures make it less of a pain (you still have the pain of changing code at all the layers).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a huge topic and should be dealt with separately.&lt;/P&gt;
&lt;P&gt;Thanks to Paul Laudeman for summarizing my views, though I didn&amp;#8217;t express an opinion on interop. I believe that discussion is worth a separate post. &lt;SPAN style="FONT-FAMILY: Wingdings; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-char-type: symbol; mso-symbol-font-family: Wingdings"&gt;&lt;SPAN style="mso-char-type: symbol; mso-symbol-font-family: Wingdings"&gt;J&lt;/SPAN&gt;&lt;/SPAN&gt; Here is the link to his summary http://dotnetjunkies.com/weblog/plaudeman/archive/12212003.aspx&lt;/P&gt;
&lt;P&gt;At the end of the day, I have changed my positions quite a few times in the past. May be it is time to change my opinion now. May be not.&lt;/P&gt;
&lt;P&gt;But, I appreciate your critical comments though. As na&amp;#239;ve as I may sound, I think I am a good learner &lt;SPAN style="FONT-FAMILY: Wingdings; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-char-type: symbol; mso-symbol-font-family: Wingdings"&gt;&lt;SPAN style="mso-char-type: symbol; mso-symbol-font-family: Wingdings"&gt;J&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=45028" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ramkoth/archive/tags/Data/default.aspx">Data</category></item><item><title>Futility of Object-Relational technologies</title><link>http://blogs.msdn.com/ramkoth/archive/2003/12/21/44935.aspx</link><pubDate>Mon, 22 Dec 2003 02:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:44935</guid><dc:creator>ramkoth</dc:creator><slash:comments>18</slash:comments><comments>http://blogs.msdn.com/ramkoth/comments/44935.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ramkoth/commentrss.aspx?PostID=44935</wfw:commentRss><description>&amp;nbsp;OR (Object-Relational) technologies attempt to abstract OO developer from knowing intricacies of relational database. It does so by de-coupling the object definition from its persistence. Persistence layer will do the 'right thing' to persist information in the persistent store. It also knows how to fetch information from the persistent store. In general, most technologies use OO language types such as classes or in some case structs to map to tables or views with properties of the type mapped to columns or fields. This post discusses some of the short falls of such technologies.
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;One of the main issues with attempting to map relational tables to objects is that of flexibility. For example, think of application like Outlook which lets you choose whatever the fields you want to see (like Size, received time, subject etc). In fact this feature is called Field Chooser. I am sure most of the applications require end-users to select a view of data. Relational database lets you create views of a table through select statement. What is the equivalent in OO world? As far as I know there is no way one can create a view of an object statically, leave alone dynamic definition. OR guys may object to this, possibly saying that the application can ignore the fields that it doesn't want to see. This is a lousy argument at best. For example, think of an Employee object that has hundreds of attributes. Let's say that I want to search for an employee and all I want to see is the name, title and department. Let's say that the search returned with 1000 possible matches. If you use OR technology, you probably have 1000 employee object instances out there that contains all the attributes (even though the attributes may not be set) that the user doesn't want to see, but still occupying memory. This is not the optimal use of working-set. Again, OO guys might object to this by saying that in today's systems memory doesn't matter. In my opinion, it always matters and world class applications always use memory intelligently and spartan use of memory is always preferable.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Another related issue is that binding the result sets to presentation layer widgets such as grid or list controls. In the above said case, where the view is dynamic based on user choice, application developer has to write some code to map the object or object set to controls. Instead, if you use datasets, then you don't have to do any extra tricks to map to user controls.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Yet another issue is that of security. For example, certain users may have access to only certain fields. In this case again, application has to write additional amount of code to enforce the authorization.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;There are other cases, where OR has no answers at all. For example, continuing the flexibility argument, there are cases, where an application have to send a free-form SQL query to RDBMS. I can think of situations where the users are provided with a flexible interface where users can choose what they want to see and they can define search predicate. One fine example is Query by example (QBE). The implementation might require the application to generate a dynamic sql on the fly that may involve one or more tables (again determined on the fly). I would like to call this dynamic&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;'aggregation' of data from many different tables. There is no way by which one can achieve this functionality using current OR technology. Objects/classes, by definition are inflexible data-structures. As of today, type system supported by the OO languages or the runtime they are based on, do not support this semantics.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;Predominant implementations of OR technologies uses type system provided by the host language. For example, if you take Java or CLR or C++, &lt;SPAN style="FONT-STYLE: italic"&gt;classes &lt;/SPAN&gt;are used to represent an object. Most of these languages or the runtime based on which the language compilers are developed, doesn't support dynamic modification of the types. The type system of OO languages is not flexible where as RDBMS is very flexible by its very nature. One can define a type in RDBMS system, define a view on it, define an&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;aggregated view using the semantics of relational calculus. Sure enough, RDBMS requires huge amount of meta-data that one has to supply in the form of DDL. But, that is the power of RDBMS.&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;So, the question would then be, what are the desirable characteristics of the data-structure that represents relational information in-memory. The main characteristic, I would think of, is that the data-structure should be flexible - one should be able to make modifications to the structure on the fly. I can think of three possible data structures that fit this criteria. They are&lt;/P&gt;
&lt;P style="FONT-SIZE: 10pt; MARGIN: 0in; FONT-FAMILY: Verdana; mso-outline-level: 1"&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL style="MARGIN-TOP: 0in; MARGIN-BOTTOM: 0in; MARGIN-LEFT: 0.5in; DIRECTION: ltr; unicode-bidi: embed" type=disc&gt;
&lt;LI style="MARGIN-TOP: 0px; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; mso-outline-level: 1"&gt;&lt;SPAN style="FONT-FAMILY: Verdana"&gt;Datasets&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; mso-outline-level: 1"&gt;&lt;SPAN style="FONT-FAMILY: Verdana"&gt;XML&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI style="MARGIN-TOP: 0px; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0px; VERTICAL-ALIGN: middle; mso-outline-level: 1"&gt;&lt;SPAN style="FONT-FAMILY: Verdana"&gt;Roll your own which will ultimately look like datasets.&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=44935" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ramkoth/archive/tags/Data/default.aspx">Data</category></item></channel></rss>