<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="RSS_xslt_style.asp" version="1.0" ?>
<rss version="2.0" xmlns:WebWizForums="http://syndication.webwiz.co.uk/rss_namespace/">
 <channel>
  <title>DevForce Community Forum : Concurrency in Master/Detail Relationships</title>
  <link>http://www.ideablade.com/forum/</link>
  <description>This is an XML content feed of; DevForce Community Forum : DevForce Classic : Concurrency in Master/Detail Relationships</description>
  <pubDate>Fri, 12 Jun 2026 11:31:46 -700</pubDate>
  <lastBuildDate>Wed, 06 Jun 2007 11:32:51 -700</lastBuildDate>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Web Wiz Forums 9.69</generator>
  <ttl>360</ttl>
  <WebWizForums:feedURL>www.ideablade.com/forum/RSS_post_feed.asp?TID=36</WebWizForums:feedURL>
  <image>
   <title>DevForce Community Forum</title>
   <url>http://www.ideablade.com/forum/forum_images/IdeaBlade_logo_tm.png</url>
   <link>http://www.ideablade.com/forum/</link>
  </image>
  <item>
   <title>Concurrency in Master/Detail Relationships :      Level 400 DevForce Express  View...</title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=36&amp;PID=96#96</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=21" rel="nofollow">IdeaBlade</a><br /><strong>Subject:</strong> 36<br /><strong>Posted:</strong> 06-Jun-2007 at 11:32am<br /><br /><strong><EM><FONT face="Times New Roman" size=3><DIV><TABLE cellSpacing=0 cellPadding=7 width="100%"><T><TR vAlign=top =#ffffff><TD colSpan=2 height=18><a href="http://rs6.net/tn.jsp?t=ir8xd7bab.0.lirg6ubab.zufnlmbab.2355&amp;ts=S0229&amp;p=http%3A%2F%2Fwww.ideablade.com%2Ftech_tips_definiti&#111;ns.htm" target="_blank"><FONT face="Times New Roman" size=3>Level 400 <BR title=http://rs6.net/tn.jsp?t=ir8xd7bab.0.lirg6ubab.zufnlmbab.2355&amp;ts=S0229&amp;p=http%3A%2F%2Fwww.ideablade.com%2Ftech_tips_definiti&#111;ns.htm>DevForce Express</FONT></A></TD><TD width="43%"><DIV align=center><a href="http://rs6.net/tn.jsp?t=ir8xd7bab.0.nblx5vbab.zufnlmbab.2355&amp;ts=S0229&amp;p=http%3A%2F%2Fwww.ideablade.com%2Ftechtips_summary.html" target="_blank"><FONT face="Times New Roman" size=3>View Archived Tech Tips</FONT></A></DIV></TD><TD><DIV align=right><FONT color=#000000>Feb 2, 2007</FONT></DIV></TD></TR><TR vAlign=center =#ffffff><TD width="8%" height=18><strong><FONT color=#000000><a href="http://rs6.net/tn.jsp?t=ir8xd7bab.0.nblx5vbab.zufnlmbab.2355&amp;ts=S0229&amp;p=http%3A%2F%2Fwww.ideablade.com%2Ftechtips_summary.html" target="_blank"><img src="http://www.ideablade.com/images/lightbulb.jpg" height="33" width="33" border="0" alt="View%20all%20Tech%20Tips" /></A></FONT></strong></TD><TD colSpan=3><strong>Concurrency in Master / Detail Relationships</strong></TD></TR></T></TABLE></DIV></FONT></EM></strong><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">What is the best way to detect concurrency violations in master / detail relationships?<?:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><FONT face="Times New Roman"><B><SPAN style="FONT-SIZE: 12pt">An Example</SPAN></B><SPAN style="FONT-SIZE: 12pt"><O:P></O:P></SPAN></FONT></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Here's a sad tale of Orders and OrderDetails&nbsp;gone bad:<O:P></O:P></FONT></SPAN></P><OL ="1"><LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l0 level1 lfo2" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Abby creates an Order with three OrderDetails, (1a), (1b), and (1c).<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l0 level1 lfo2" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Abby saves the Order and its details. <O:P></O:P></FONT></SPAN><LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l0 level1 lfo2" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Abby goes to lunch.<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l0 level1 lfo2" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Bob picks up the same Order and changes its details, adding (1d) and deleting (1b).<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l0 level1 lfo2" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Bob saves his changes. <O:P></O:P></FONT></SPAN><LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l0 level1 lfo2" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">When Abby returns from lunch, she&nbsp;still has the original Order and details in her&nbsp;cache; <O:P></O:P></FONT></SPAN><LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l0 level1 lfo2" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Abby continues working on details (1a) and (1c) but doesn't touch (1b) or the Order itself.<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l0 level1 lfo2" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Abby saves her work.<O:P></O:P></FONT></SPAN></LI></OL><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><FONT face="Times New Roman"><SPAN style="FONT-SIZE: 12pt; mso-font-kerning: 16.0pt">Her save will succeed. She won't hear a peep from the database or DevForce. There is no concurrency violation because Abby's changes to (1a) and (1c) are independent of&nbsp;Bob's work on (1b) and (1d). </SPAN><SPAN style="FONT-SIZE: 12pt"><O:P></O:P></SPAN></FONT></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><FONT face="Times New Roman"><SPAN style="FONT-SIZE: 12pt; mso-font-kerning: 16.0pt">This is not good. Abby will not know that Bob has changed the Order. The order Abby thought she created is not the order stored in the database. Abby, Bob, or the customer are in for an unpleasant surprise.</SPAN><SPAN style="FONT-SIZE: 12pt"><O:P></O:P></SPAN></FONT></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><FONT face="Times New Roman"><B><SPAN style="FONT-SIZE: 12pt; mso-font-kerning: 16.0pt">Dependency Automation</SPAN></B><SPAN style="FONT-SIZE: 12pt"><O:P></O:P></SPAN></FONT></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Folks often wonder if DevForce can detect the problem and signal a concurrency violation. DevForce "knows" about the relationship between Order and its OrderDetails. Perhaps it should infer the implications of that relationship. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">In fact, DevForce won't detect the problem and should not draw any conclusions about the relationships among the entities. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">We begin to see why when we observe that few "master / detail" relationships are as strong as the one between an Order and its details. For example, Customer has a "master / detail" relationship to Order. We usually don't mind if Abby and Bob make changes to separate orders of the same customer. So how is that different from Abby and Bob changing separate details of the same order? <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">If you are a UML junky, you know to classify these two relationships differently. The Customer / Order relationship is an <B>"Association"</B>; we say that a customer <B>"has orders"</B>. The Order / Order relationship is called a <B>"Composition"</B>; we say that an Order <B>"is made up of"</B> its OrderDetails". "Has a" is not as strong as "is made up of". <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">DevForce object mapping doesn't distinguish among the types of relationship. Some other mapping products allow you to make this distinction. Is DevForce deficient in this respect? Should we enable marking the "Order / OrderDetail" relationship as a "composition" and enforce the implications?<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">We've certainly thought about it. It isn't technically daunting; relationship marking is easy and cascading inserts, updates, and deletes isn't much harder. But experience teaches us that the "implications" are not as clear as they seem. For example, we generally don't worry when two users work on orders for the same customer; but sometimes we do. The customer could have a credit limit. There could be a business rule that requires senior management approval when the sum of all order totals exceeds a threshold. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Should we say that Customer / Order is a composition too and prevent simultaneous changes by multiple users to any of a customer's orders? That may not fly in the real world. And there is no telling where to stop once you start locking up the object graph with composition constraints. What if the order total threshold changes? Maybe we better lock up that one. How about the customer's headquarters address? There could be sales tax implications; I guess we should lock that up too. Soon no one can do anything for fear of some dependency somewhere. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">We've chosen to stay out of your way. We think you should decide your own business rules and how to enforce them by writing code for the purpose. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Which is why we get that question at least once a month: how do I write the code so that orders and their details are treated as one thing?<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><FONT face="Times New Roman"><B><SPAN style="FONT-SIZE: 12pt">"Root Entity Marker"</SPAN></B><SPAN style="FONT-SIZE: 12pt"> <O:P></O:P></SPAN></FONT></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Suppose we're certain that any change to either the order or any of its details is a change to the entire order. We'll agree to deal with the nuances of customer credit limits another way. Meanwhile, we want the application to enforce the integrity of the order with respect to its details. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">I suggest a simple expedient: whenever we save changes to an OrderDetail, we save its Order too. Of course we can only save entities that have been changed so we'll have to mark the Order "dirty". <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">We can generalize the problem and its solution. Whenever we detect a network (AKA, a graph) of objects which should be treated as a single unit, we should (a) identify the "Root Entity", (b) save the root entity when saving a change to any object in the graph , and (c) ensure that we save the combined order changes in a single transaction. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Order is the "Root Entity" in our example. Let's reexamine the story of Abby and Bob, picking up at the point when Bob saves his changes. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">He didn't touch the Order object but the application marked it "dirty" anyway and saved it along with the addition of (1d) and the deletion of (1b). Abby's cached copy of the Order is no longer "current" with respect to the database. When she tries to save her order detail changes, the application marks her order dirty and tries to save it along with her changes to (1a) and (1c). <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">This time she gets a concurrency violation. Although Abby's and Bob's changes to order details did not collide - they worked on different OrderDetail objects - Abby's modified order no longer matches the order in the database - the one saved by Bob. DevForce will recognize a concurrency error on the order and the transaction will fail. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><FONT face="Times New Roman"><B><SPAN style="FONT-SIZE: 12pt">How to Dirty the Root Entity</SPAN></B><SPAN style="FONT-SIZE: 12pt"> <O:P></O:P></SPAN></FONT></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">It is easy to "dirty" a DevForce entity even if it was previously unmodified:<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 5pt 0in; LINE-HEIGHT: 13pt" ="Ms&#111;normal"><B><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: Helvetica">C#:</SPAN></B><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: Helvetica"><O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt 0.25in" ="CodeSnippet"><strong><FONT size=2><FONT><FONT face="Courier New"><FONT color=#808080>public static </FONT><SPAN style="COLOR: #006666">Entity</SPAN><FONT color=#808080> </FONT><SPAN style="COLOR: black">EnsureModified(</SPAN><SPAN style="COLOR: #006666">Entity</SPAN><FONT color=#808080> </FONT><SPAN style="COLOR: black">pEntity) {</SPAN></FONT></FONT></FONT></strong><strong><FONT size=2><FONT><FONT face="Courier New"><FONT color=#808080> <BR>&nbsp;&nbsp;if </FONT><SPAN style="COLOR: black">( pEntity.RowState ==</SPAN><FONT color=#808080> </FONT><SPAN style="COLOR: #006666">DataRowState</SPAN><SPAN style="COLOR: black">.Unchanged ) {</SPAN></FONT></FONT></FONT></strong><strong><FONT size=2><FONT><FONT face="Courier New"><FONT color=#808080> <BR></FONT><SPAN style="COLOR: black">&nbsp;&nbsp;&nbsp;&nbsp;( (</SPAN><SPAN style="COLOR: #006666">DataRow</SPAN><FONT color=#808080>) </FONT></FONT></FONT></FONT></strong><SPAN style="COLOR: black"><FONT face="Courier New" size=2><strong>pEntity ).SetModified(); <BR>&nbsp;&nbsp;}</strong></FONT></SPAN><FONT face="Courier New" color=#808080 size=2><strong> <BR>return </strong></FONT><strong><FONT size=2><FONT><FONT face="Courier New"><SPAN style="COLOR: black">pEntity; <BR>} </SPAN><SPAN style="FONT-SIZE: 12pt; mso-bidi-font-size: 8.0pt"><O:P></O:P></SPAN></FONT></FONT></FONT></strong></P><P style="MARGIN: 5pt 0in; LINE-HEIGHT: 13pt" ="Ms&#111;normal"><SPAN><strong>VB.NET:</strong><O:P></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt 0.25in" ="CodeSnippet"><strong><FONT size=2><FONT><FONT face="Courier New"><SPAN style="COLOR: blue">Public Shared Function</SPAN><FONT color=#808080> </FONT><SPAN style="COLOR: black">EnsureModified</SPAN><FONT color=#808080>(</FONT><SPAN style="COLOR: blue">ByVal</SPAN><FONT color=#808080> </FONT><SPAN style="COLOR: black">pEntity</SPAN><FONT color=#808080> </FONT><SPAN style="COLOR: blue">As</SPAN><FONT color=#808080> </FONT><SPAN style="COLOR: #006666">Entity</SPAN><FONT color=#808080> ) </FONT><SPAN style="COLOR: blue">As</SPAN><FONT color=#808080> </FONT><SPAN style="COLOR: #006666">Entity</SPAN></FONT></FONT></FONT></strong><strong><FONT size=2><FONT><FONT face="Courier New"><FONT color=#808080> <BR></FONT><SPAN style="COLOR: blue">&nbsp;&nbsp;If</SPAN><FONT color=#808080> pEntity.RowState = </FONT><SPAN style="COLOR: #006666">DataRowState</SPAN><FONT color=#808080>.Unchanged </FONT><SPAN style="COLOR: blue">Then</SPAN></FONT></FONT></FONT></strong><strong><FONT size=2><FONT><FONT face="Courier New"><FONT color=#808080> <BR></FONT><SPAN style="COLOR: blue">&nbsp;&nbsp;&nbsp;&nbsp;CType</SPAN><FONT color=#808080>(pEntity, </FONT><SPAN style="COLOR: #006666">DataRow</SPAN></FONT></FONT></FONT></strong><strong><FONT size=2><FONT><FONT face="Courier New"><FONT color=#808080>).SetModified() <BR></FONT><SPAN style="COLOR: blue">&nbsp;&nbsp;End If</SPAN></FONT></FONT></FONT></strong><strong><FONT size=2><FONT><FONT face="Courier New"><FONT color=#808080> <BR></FONT><SPAN style="COLOR: blue">&nbsp;&nbsp;Return</SPAN></FONT></FONT></FONT></strong><FONT size=2><FONT><FONT face="Courier New"><FONT color=#808080><strong> pEntity <BR></strong></FONT><strong><SPAN style="COLOR: blue">End Function</SPAN><SPAN style="FONT-FAMILY: Helvetica"><O:P></O:P></SPAN></strong></FONT></FONT></FONT></P><P style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: 13pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: Helvetica">&nbsp;<O:P></O:P></SPAN></P><P style="MARGIN: 5pt 0in; LINE-HEIGHT: 13pt" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: Helvetica">When to do so takes a tad more programming. A full code sample wouldn't fit in this tip (contact us for it) but we can benefit right now from a sketch of the primary scenario.<O:P></O:P></SPAN></P><OL ="1"><LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo1" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">The application tries to save Abby's OrderDetails.<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo1" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">DevForce raises its SavingEvent. <O:P></O:P></FONT></SPAN><LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo1" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">The SavingEventArgs provide a list of entities that are about to be saved.<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo1" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Your SavingEventHandler calls each listed entity's Validate method.<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo1" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">The OrderDetail Validate method first validates the detail. <O:P></O:P></FONT></SPAN><LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo1" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">It next passes the parent Order to EnsureModified().<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo1" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">It adds the Order to the list of entities to save.<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo1" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">The Order itself gets validated.<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo1" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">The SavingEventHandler returns without validation errors.<O:P></O:P></FONT></SPAN> <LI style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; tab-stops: list .5in; mso-list: l1 level1 lfo1" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">DevForce saves the Order and the changed OrderDetails.<O:P></O:P></FONT></SPAN></LI></OL><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><BR><FONT face="Times New Roman"><B>User Experience</B> <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Remember that Abby was at lunch when Bob saved his changes. Abby returned and spent fifteen more minutes working on the details before trying to save. Thanks to our new logic, the application detected a concurrency violation and told her "Sorry Abby, I can't save your work." <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Abby is not happy. Actually, she is furious. If we're lucky, she turns her ire on Bob. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Of course it is really our fault. Bob didn't know that Abby was working on the order and Abby didn't know that Bob had taken over. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">We might try to help her reconcile the differences - and perhaps merge her changes into Bob's. I think this is an exercise in futility. We'll burden our application with crushing complexity while doing little to improve Abby's mood. We should concentrate instead on preventing the problem in the first place. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">I recommend that you combine the "Root Entity Marker" approach with a "Root Entity Reservation" system. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><FONT face="Times New Roman"><B><SPAN style="FONT-SIZE: 12pt">Root Entity Reservation</SPAN></B><SPAN style="FONT-SIZE: 12pt"> <O:P></O:P></SPAN></FONT></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">We could require a user to reserve (or "check out") the root entity before she begins work on it or any of its parts. Accordingly we begin by adding a "ReservedByUserId" column to the Order table. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">&#091;Aside: this is just one implementation. Maybe we can't change an existing table, in which case we could create a new "OrderReservation" table. "OrderReservation" becomes the "root entity" in our drama with Order and its OrderDetails in supporting roles.&#093; <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">When Abby first saves her new Order, the UI stamps the ReservedByUserId with her user id. Then Bob looks at the Order in a list of pending work. He sees that Abby has reserved it. The application won't let him edit it. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Abby returns from lunch. She still owns the order. She makes her changes, saves her work, and releases her reservation. Now Bob can take over if he still wants to do so. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Let's suppose he does. The UI stamps the order with his user id and attempts to save it. Had the save succeeded, the UI would have opened the "order graph" for him to edit. As it happens, Charles from across the hall reserves the order a split second ahead of Bob, causing Bob's save to fail. Bob's UI refreshes its cached copy of the order so he can see that Charles has it now. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><FONT face="Times New Roman"><B><SPAN style="FONT-SIZE: 12pt">Reserve, Don't Lock</SPAN></B><SPAN style="FONT-SIZE: 12pt"> <O:P></O:P></SPAN></FONT></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Observe that we updated the order. We didn't lock the table. Locking the table impairs performance. Worse, we would have no easy way of breaking the lock if we had to cancel the reservation. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Suppose the order turns critical while Abby was out for lunch. Bob steps in because there is a customer emergency. As it happens, Bob is a supervisor with the authority to override Abby's reservation. He does so and reserves the order for himself. The application queues up an alert for Abby; when she returns from lunch, she sees immediately that Bob has taken over. She calls Bob to discuss her pre-lunch changes so that he can enter them himself. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">It's easy to enrich the reservation facility. We could add a timeout of, say, twenty minutes after which the reservation is cleared. The UI could display a countdown clock, sound a warning tone, and let Abby renew her reservation if she needed more time. If her reservation expired, she could try to re-reserve it; she'd be fine as long as Bob and Charlie left the order alone. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">This scheme has a long history of success. The reservation system is transparent and familiar. Users "get it". They see what is going on and accept the consequences of expired or canceled reservations. It works for management too, stimulating "ownership" among the users and providing the flexibility necessary to cope with emergencies. <O:P></O:P></FONT></SPAN></P><P style="MARGIN: 8pt 0in 0pt; LINE-HEIGHT: 13pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" ="Ms&#111;normal"><SPAN style="FONT-SIZE: 12pt"><FONT face="Times New Roman">Consider the <B>"Root Entity Marker" </B>and<B> "Root Entity Reservation"</B> patterns the next time you face a graph of master / detail relationships.<O:P></O:P></FONT></SPAN></P><span style="font-size:10px"><br /><br />Edited by IdeaBlade - 09-Jul-2007 at 12:31pm</span>]]>
   </description>
   <pubDate>Wed, 06 Jun 2007 11:32:51 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=36&amp;PID=96#96</guid>
  </item> 
 </channel>
</rss>