<?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 : Multi-Tenant Database</title>
  <link>http://www.ideablade.com/forum/</link>
  <description>This is an XML content feed of; DevForce Community Forum : DevForce Classic : Multi-Tenant Database</description>
  <pubDate>Wed, 10 Jun 2026 21:38:56 -700</pubDate>
  <lastBuildDate>Wed, 09 Jul 2008 08:17:38 -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=882</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>Multi-Tenant Database : We have recently had one customer...</title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=882&amp;PID=3201#3201</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=23" rel="nofollow">davidklitzke</a><br /><strong>Subject:</strong> 882<br /><strong>Posted:</strong> 09-Jul-2008 at 8:17am<br /><br />We have recently had one customer develop an application with multi-tenant capabilities.&nbsp; They did this using a&nbsp;capability that&nbsp;you describe in your post.&nbsp; This capability allows you to modify every outgoing query to the database.&nbsp; In the example below from the "Best Practices" section of the Developer's Guide, this capabability can be used to implement "Soft Deletes", bur as I said earlier, we successfully used this same capability to implement mult-tenant database queries: <DIV>&nbsp;</DIV><DIV><H3 style="MARGIN: 12pt 0in 3pt -0.25in"><A name=_Toc194318799></A>&nbsp;&nbsp;&nbsp;&nbsp; <A name=_Toc174789605><SPAN style="mso-bookmark: _Toc194318799"><strong><FONT size=5>Implementing “Soft Deletes”</FONT></strong></SPAN></A></H3><P style="MARGIN: 8pt 0in 0pt" ="Ms&#111;normal"><FONT size=2><FONT face="Times New Roman"><I style="mso-bidi-font-style: normal"><strong>Question:</strong></I> “For some of our Entities, we want the corresponding database records not to be physically deleted when a User deletes the Entity and saves changes. Instead, the corresponding record should just be flagged as deleted in the database. </FONT></FONT></P><P style="MARGIN: 8pt 0in 0pt" ="Ms&#111;normal"><FONT face="Times New Roman" size=2>“To accomplish this, we have a Status column that contains an enum value stating whether the row is deleted or not. When querying tables that include such columns, the Status always needs to be specified as a parameter to filter out the deleted records.</FONT></P><P style="MARGIN: 8pt 0in 0pt" ="Ms&#111;normal"><FONT face="Times New Roman" size=2>“I did not find an obvious way to implement this delete behaviour in our Entity classes.<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>Do you have any samples?</FONT></P><P style="MARGIN: 8pt 0in 0pt" ="Ms&#111;normal"><FONT face="Times New Roman" size=2>“Also, how can we extend or override DevForce’s GetEntity() methods so they filter out the deleted entities by default, without any additional clause?”</FONT></P><P style="MARGIN: 8pt 0in 0pt" ="Ms&#111;normal"><FONT size=2><FONT face="Times New Roman"><B style="mso-bidi-font-weight: normal"><I style="mso-bidi-font-style: normal">Answer:</I> </B>This is a pattern we often see. There are a number of ways to go about this:</FONT></FONT></P><P style="MARGIN: 8pt 0in 0pt 0.75in; TEXT-INDENT: -0.5in; mso-list: l0 level1 lfo1; tab-stops: list .75in" ="Ms&#111;normal"><FONT face="Times New Roman"><SPAN style="mso-list: Ignore"><FONT size=2>1.</FONT><SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><FONT size=2>Add a "Fetching" handler to the PersistenceManager that examines the query and adds this clause if necessary. The Fetching event is raised just before the PersistenceManager sends a query to the server; the query is included in the event args for the Fetching handler, and you can modify it before DevForce applies it.</FONT></FONT></P><P style="MARGIN: 8pt 0in 0pt 0.75in; TEXT-INDENT: -0.5in; mso-list: l0 level1 lfo1; tab-stops: list .75in" ="Ms&#111;normal"><FONT face="Times New Roman"><SPAN style="mso-list: Ignore"><FONT size=2>2.</FONT><SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><FONT size=2>Add a "Fetched" handler to the PersistenceManager that removes "inactive" entities from the cache if they happen to be picked up (e.g., through a span).<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>This is essential if you add spans that could retrieve an "inactive/deleted" record. You will want to use the overload of PersistenceManager.RemoveEntities() method that does not disturb the query cache. </FONT></FONT></P><P style="MARGIN: 8pt 0in 0pt 0.75in; TEXT-INDENT: -0.5in; mso-list: l0 level1 lfo1; tab-stops: list .75in" ="Ms&#111;normal"><FONT face="Times New Roman"><SPAN style="mso-list: Ignore"><FONT size=2>3.</FONT><SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><FONT size=2>Create a custom subclass of RdbQuery that always adds this clause.<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>Then always use your class instead of the raw RdbQuery.</FONT></FONT></P><P style="MARGIN: 8pt 0in 0pt 0.75in; TEXT-INDENT: -0.5in; mso-list: l0 level1 lfo1; tab-stops: list .75in" ="Ms&#111;normal"><FONT face="Times New Roman"><SPAN style="mso-list: Ignore"><FONT size=2>4.</FONT><SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><FONT size=2>Write your own PersistenceManager adapter that covers GetEntities, etc.</FONT></FONT></P><P style="MARGIN: 8pt 0in 0pt" ="Ms&#111;normal"><FONT face="Times New Roman" size=2>The "Fetching" and "Fetched" event handlers are strong candidates because they work even within Relation Properties. Consider, for example, Order.OrderDetails. If the OrderDetail object has an " ActiveFlag<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>column, you have to intercept the hidden query either by the use of a "Fetching" handler, or by overriding the "OrderDetails" property itself.</FONT></P><P style="MARGIN: 8pt 0in 0pt" ="Ms&#111;normal"><FONT face="Times New Roman" size=2>Let's assume that all business objects that have an "ActiveFlag" property descended from an abstract entity class (e.g., "ActiveEntity"). </FONT></P><P style="MARGIN: 8pt 0in 0pt" ="Ms&#111;normal"><FONT face="Times New Roman" size=2>You might initialize your PersistenceManager as follows:</FONT></P><DIV style="BORDER-RIGHT: #666699 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: #666699 1pt solid; PADDING-LEFT: 4pt; PADDING-BOTTOM: 4pt; MARGIN-LEFT: 0.25in; BORDER-LEFT: #666699 1pt solid; MARGIN-RIGHT: 0.25in; PADDING-TOP: 4pt; BORDER-BOTTOM: #666699 1pt solid; mso-element: para-border-div; mso-border-alt: solid #666699 .5pt; e0e0e0: "><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole">private void InitializePm() {<?: prefix = o ns = "urn:schemas-microsoft-com:office:office" /><O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>mManager = PersistenceManager.DefaultManager;<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>// other stuff<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>mManager.Fetching += new EventHandler&lt;EntityFetchingEventArgs&gt;(mManager_Fetching);<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>mManager.Fetched += new EventHandler&lt;EntityFetchedEventArgs&gt;(mManager_Fetched);<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole">}<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><O:P><FONT face="Lucida C&#111;nsole">&nbsp;</FONT></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><O:P><FONT face="Lucida C&#111;nsole">&nbsp;</FONT></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole">static void mManager_Fetching(object sender, EntityFetchingEventArgs e) {<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>IdeaBlade.Persistence.Rdb.RdbQuery q = e.Query;<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>if ( q.EntityType is ActiveEntity ) {<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>q.AddClause("ActiveFlag", EntityQueryOp.EQ, true); // '1' == true<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole">}<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><O:P><FONT face="Lucida C&#111;nsole">&nbsp;</FONT></O:P></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole">static void mManager_Fetched(object sender, EntityFetchedEventArgs e) {<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>List&lt;Entity&gt; removeList = new List&lt;Entity&gt;();<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>foreach ( Entity obj in e.Entities ) {<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>ActiveEntity ae = obj as ActiveEntity;<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>if (ae != null &amp;&amp; !ae.IsActive) {<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>removeList.Add(obj);<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp;&nbsp;&nbsp; </SPAN>}<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp; </SPAN>}<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole"><SPAN style="mso-spacerun: yes">&nbsp;</SPAN><SPAN style="mso-spacerun: yes">&nbsp;</SPAN>mManager.RemoveEntities(removeList, false); // remove but don't clear query cache.<O:P></O:P></FONT></SPAN></P><P style="MARGIN: 0in 0in 0pt; e0e0e0: " ="syntax"><SPAN style="FONT-SIZE: 8pt"><FONT face="Lucida C&#111;nsole">} <O:P></O:P></FONT></SPAN></P></DIV><P style="MARGIN: 8pt 0in 0pt" ="Ms&#111;normal"><FONT face="Times New Roman" size=2>There is another approach that might tempt you, but which should be avoided. There is an "SQL Where Clause" mapping option which lets you put a filtering constraint in the object definition itself. This is great if the value of the filter column is invariant. It is not good if the value of the filter column can change -- as is the case with the "inactive" or "deleted" column.<SPAN style="mso-spacerun: yes">&nbsp; </SPAN>Therefore, do not consider this option.</FONT></P></DIV><span style="font-size:10px"><br /><br />Edited by davidklitzke - 09-Jul-2008 at 8:20am</span>]]>
   </description>
   <pubDate>Wed, 09 Jul 2008 08:17:38 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=882&amp;PID=3201#3201</guid>
  </item> 
  <item>
   <title>Multi-Tenant Database : Hi there,I am in the process of...</title>
   <link>http://www.ideablade.com/forum/forum_posts.asp?TID=882&amp;PID=3197#3197</link>
   <description>
    <![CDATA[<strong>Author:</strong> <a href="http://www.ideablade.com/forum/member_profile.asp?PF=350" rel="nofollow">gavin.dell</a><br /><strong>Subject:</strong> 882<br /><strong>Posted:</strong> 08-Jul-2008 at 10:51pm<br /><br />Hi there,<br><br>I am in the process of evaluating DevForce as a potential fit for our Data Access and Business Object requirements. At this point, I have one question:<br><br>We have a multi-tenant data store (SQL Server 2005) which requires the execution of a block of SQL (or a stored procedure) before the any SQL statements are executed against the connection.&nbsp; This stored procedure sets the "tenant" state for the duration of this connection.&nbsp; In some other ORM's that I have come across, you can specify a SQL statement to execute before using the connection - usually touted as connection validation SQL - and this suits our purposes. Does DevForce have a similar mechanism or is there some functionality we can implement to provide this?<br><br>Many thanks.<br><br>Gavin<br>]]>
   </description>
   <pubDate>Tue, 08 Jul 2008 22:51:22 -700</pubDate>
   <guid isPermaLink="true">http://www.ideablade.com/forum/forum_posts.asp?TID=882&amp;PID=3197#3197</guid>
  </item> 
 </channel>
</rss>