<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NetQuarry &#187; Features</title>
	<atom:link href="http://www.netquarry.com/index.php/category/features/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.netquarry.com</link>
	<description>The Enterprise Application Platform</description>
	<lastBuildDate>Wed, 21 Apr 2010 18:30:17 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>TypedMappers</title>
		<link>http://www.netquarry.com/index.php/2009/02/typedmappers-1041/</link>
		<comments>http://www.netquarry.com/index.php/2009/02/typedmappers-1041/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 02:39:58 +0000</pubDate>
		<dc:creator>Ryan Reid</dc:creator>
				<category><![CDATA[Features]]></category>

		<guid isPermaLink="false">http://www.netquarry.com/?p=41</guid>
		<description><![CDATA[A TypedMapper is a helpful, extrememly lightweight type-safe wrapper class around a NetQuarry Mapper object.

You typically use a TypedMapper as a helper class in an extension. You can create a TypedMapper and attach it to the sender (IMapper) of the event or you can use the TypedMapper derivative to create a new mapper - either for the purpose of creating a new row or reading/updating an existing one. Connecting a TypedMapper via one of the constructors or TypedMapper.Attach is very inexpensive and generally a safer way to work with a mapper.
]]></description>
			<content:encoded><![CDATA[<p>A TypedMapper is a helpful, extrememly lightweight type-safe wrapper class around a NetQuarry Mapper object.</p>
<p>You typically use a TypedMapper as a helper class in an extension. You can create a TypedMapper and attach it to the sender (IMapper) of the event or you can use the TypedMapper derivative to create a new mapper &#8211; either for the purpose of creating a new row or reading/updating an existing one. Connecting a TypedMapper via one of the constructors or TypedMapper.Attach is very inexpensive and generally a safer way to work with a mapper.</p>
<p>The TypedMapper is an abstract base class, which means that you have to use our generator to generate derived classes that wrap your mappers. The ONLY potential drawback to using a TypedMapper derivative vs. the Mapper as is is that you will need to update (re-generate) the classes as you make metadata changes. On the applications that we (NetQuarry) are personally managing we are putting the generation code after we save the metadata and check-in the class file. We are recomending that you keep the generated classes more or less stand-alone (e.g. in its own assembly) and without any dependencies on other code.</p>
<p>TypedMapper objects that have custom functionality added to them should all be placed in the Data project.  This allows that functionality to be shared with other consumers.  You can add TypedMapper objects anywhere in your code base and add different functions to each instance.  That is not recommended.</p>
<p>You create a typed mapper object by deriving the class from the equivalent generated template typed mapper object.  The template object gives you all the type safe declarations for fields on the mapper that are on the mapper when flavor 0 is applied to the mapper.  All fields with an include flavor are not in a generated TypedMapper.</p>
<p>To declare a typed mapper, you derive your class from the generated class template:</p>
<p><span class="code-blue">public class</span> <span class="code"><span class="code-teal">People</span> : Comensura.Data.Generated.<span class="code-teal">people</span>&lt;<span class="code-teal">People</span>&gt;</span><br />
<span class="code-blue">public class</span> <span class="code"><span class="code-teal">CompaniesTemplates</span> : Comensura.Data.Generated.<span class="code-teal">companies_templates</span>&lt;<span class="code-teal">CompaniesTemplates</span>&gt;</span></p>
<p>Or, more generally:</p>
<p><span class="code-blue">public class</span> <span class="code"><span class="code-teal">TName</span> : Application.Data.Generated.<span class="code-teal">TBase</span>&lt;<span class="code-teal">TName</span>&gt;</span></p>
<p>You give your typed mapper class the name almost exactly derived from the generated class name, removing any underscores and proper casing the letters for legibility.  Your template object is your class.  Then just treat your object like any other class and add public and private methods as appropriate.</p>
<h3>Code in Extension or TypedMapper?</h3>
<p>A commonly asked question is where to put your business logic.  The temptation is to add business logic to Mapper extensions.  Well, the basic rule of thumb is that only decision/workflow/UI logic is put in the extension and data manipulation/business logic is performed in the TypedMapper object.  </p>
<p>Having said that, there is nothing inherently wrong with putting data manipulation code in an extension as long as it’s self contained.  </p>
<p>If you add data manipulation code that is likely to be shared then you should probably think about putting that code as a method on the TypedMapper object.  The alternative to sharing code via the TypedMapper is to share the code in the Common class, but as a static method.</p>
<p>So, back to the TypedMapper object.  Remember a TypedMapper is just a mapper and whenever you call your TypedMapper functions, your logic is going to read and write data from the current row.  Of course there are many things you can do in your functions but they all relate to some operation controlled or directed by the values in the current row.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.netquarry.com/index.php/2009/02/typedmappers-1041/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Picklists</title>
		<link>http://www.netquarry.com/index.php/2006/03/picklists-1050/</link>
		<comments>http://www.netquarry.com/index.php/2006/03/picklists-1050/#comments</comments>
		<pubDate>Wed, 08 Mar 2006 03:02:00 +0000</pubDate>
		<dc:creator>Ryan Reid</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Features]]></category>

		<guid isPermaLink="false">http://www.netquarry.com/?p=50</guid>
		<description><![CDATA[We"ve spent a bunch of time solving the problem of vocabulary lists for a database application. A vocabulary list is one of those tables that have a key (typically an integer or a GUID) and some text. The “key” (primary key in DBMS-speak) is referenced by a column in a more important table. Most of the time, the end-user selects this key by choosing an item via a drop down list box that has some human readable text and the application stores the item’s “key” into the database. We call the object that solves this problem a Picklist.]]></description>
			<content:encoded><![CDATA[<p>We&#8221;ve spent a bunch of time solving the problem of vocabulary lists for a database application. A vocabulary list is one of those tables that have a key (typically an integer or a GUID) and some text. The “key” (primary key in DBMS-speak) is referenced by a column in a more important table. Most of the time, the end-user selects this key by choosing an item via a drop down list box that has some human readable text and the application stores the item’s “key” into the database. We call the object that solves this problem a Picklist.</p>
<p style="margin-top: 12pt">Normally, you solve the problem by creating a 2 column table with a key and some descriptive text. For example, say you wanted to have a status table:</p>
<p style="margin-top: 12pt">Table: status</p>
<div class="picklist-blog">
<table border="1">
<tbody>
<tr>
<td width="96" valign="top"><span>StatusID</span></td>
<td width="96" valign="top"><span>StatusText</span></td>
</tr>
<tr>
<td width="96" valign="top">1</td>
<td width="96" valign="top">Open</td>
</tr>
<tr>
<td width="96" valign="top">2</td>
<td width="96" valign="top">Closed</td>
</tr>
</tbody>
</table>
</div>
<p style="margin-top: 12pt">You might get a stab of reusability and conclude that a good idea is to store these sorts of things in a table that has a type and therefore keep yourself from having to create 300 of these tables in your database. So, the table might look like this:</p>
<p style="margin-top: 12pt">Reusable design: <span>picklist</span></p>
<div>
<table border="1">
<tbody>
<tr>
<td width="96" valign="top">id</td>
<td width="96" valign="top">description</td>
<td width="96" valign="top">list_type</td>
</tr>
<tr>
<td width="96" valign="top">1</td>
<td width="96" valign="top">Open</td>
<td width="96" valign="top">status</td>
</tr>
<tr>
<td width="96" valign="top">2</td>
<td width="96" valign="top">Closed</td>
<td width="96" valign="top">status</td>
</tr>
</tbody>
</table>
</div>
<p style="margin-top: 12pt">Now, all you have to do is change the SELECT statement and you can have one table to handle most everything. Next, you bump into a requirement where you have to store something besides and integer as the key (say, its data that you didn’t own and the key is some cryptic string). No problem, you just add another column to this list with an alternate ID (or another table, I suppose) and indicate that somehow.</p>
<p style="margin-top: 12pt">2<sup>nd</sup> try: <span>picklist</span></p>
<div>
<table border="1">
<tbody>
<tr>
<td width="96" valign="top">id</td>
<td width="96" valign="top">text_id</td>
<td width="96" valign="top">description</td>
<td width="96" valign="top">list_type</td>
</tr>
<tr>
<td width="96" valign="top">1</td>
<td width="96" valign="top">OP</td>
<td width="96" valign="top">Open</td>
<td width="96" valign="top">status</td>
</tr>
<tr>
<td width="96" valign="top">2</td>
<td width="96" valign="top">CL</td>
<td width="96" valign="top">Closed</td>
<td width="96" valign="top">status</td>
</tr>
</tbody>
</table>
</div>
<p style="margin-top: 12pt">Next, you decide that some of the items in this list are required to be shown, but you don’t want the user to select them. So you add <em>another</em> column to the table and indicate which items are disabled.</p>
<p style="margin-top: 12pt">3<sup>rd</sup> try: <span>picklist</span></p>
<div>
<table border="1">
<tbody>
<tr>
<td width="96" valign="top">id</td>
<td width="96" valign="top">text_id</td>
<td width="96" valign="top">description</td>
<td width="96" valign="top">list_type</td>
<td width="96" valign="top">disabled</td>
</tr>
<tr>
<td width="96" valign="top">1</td>
<td width="96" valign="top">OP</td>
<td width="96" valign="top">Open</td>
<td width="96" valign="top">status</td>
<td width="96" valign="top">0</td>
</tr>
<tr>
<td width="96" valign="top">2</td>
<td width="96" valign="top">CL</td>
<td width="96" valign="top">Closed</td>
<td width="96" valign="top">status</td>
<td width="96" valign="top">0</td>
</tr>
<tr>
<td width="96" valign="top">3</td>
<td width="96" valign="top">PO</td>
<td width="96" valign="top">Nearly Closed</td>
<td width="96" valign="top">status</td>
<td width="96" valign="top">1</td>
</tr>
</tbody>
</table>
</div>
<p style="margin-top: 12pt">At this point you’ve thought of several more interesting requirements so your table design ends up with several more columns to support these:</p>
<ul>
<li>Localization. If you plan to support a multi-lingual application you are very likely to need to have your vocabulary displayed in the user’s culture.</li>
<li>Readable string as a way to lookup an ID. The common case for this is when you want either to set a default value in a field but do not want to hard code some opaque primary key values in your code or you want to take some action based on the value that a user chooses and you don’t want to hardcode the primary key value.</li>
<li>Caching (or not) the items in the list. If you are going to model this, you’ve likely decided that you need to metadata tables – Picklist (for the name of the list and some attributes like “cache”), and PicklistItems (for the actual items).</li>
<li>Discrimination. Often you’ll have a requirement where the value in one column filters (or discriminates) the potential values in another. For example, you may have a list of vehicle make types in one list and based on the selection, you need to show the available models in another. The typical way to solve this is to take the value from the first control, post the results to the server, dynamically determine the new SELECT statement, and return the page with the second control filtered.</li>
<li>Two-way lookup. Often you have the value of the item’s key only and you need to find the text, but we have found that you just a frequently need to do the reverse (e.g. you have the text and you want the key). We use the reverse lookup, for example, when searching or filtering in a list – the user enters “Open” and we search for “1.”</li>
</ul>
<p style="margin-top: 12pt">The next issue you solve is how to fill the controls with the contents of these lists. The most straightforward method is to write code to open a <span>DataReader</span> with a statement like (SELECT id, description FROM <span>picklist</span> WHERE <span>list_type</span> = ‘<span>status’</span>) and add these items to a <span>DropDownList</span> control like this:</p>
<p class="code">while (dr.Read())<br />
{<br />
    listControl.Items.Add(new ListItem (dr.GetString(0), dr.GetInt32(1)));<br />
}</p>
<p style="margin-top: 12pt">Or, a better way is to bind using the DataBinding features of the DropDownList– something along these lines:</p>
<p class="code">DataTable dt = CreateTableFromPickListSQL();<br />
dropList.DataSource = dt;<br />
dropList.DataTextField = “id”;<br />
dropList.DataValueField = “description”;<br />
dropList.DataBind();</p>
<p style="margin-top: 12pt">In both cases, you are responsible for creating either the DataReader or DataTable and properly disposing of it. Most folks know how to do this, or at least they know how to cut and paste some code somewhere that does it reasonably well. It’s still a pain and generally isn’t written in such a way to promote even moderate reusability.</p>
<p style="margin-top: 12pt">Another consideration is that you may need to use one of these lists for something <em>other</em> than as a <span>DataSource</span> for a <span>DropDownList</span> control. For example, if you are displaying a table of data that has several columns which are foreign keys to your <span>picklist</span> table you either must create some sort of view to resolve these or do a lookup as you fill the list (this is almost never an option for performance reasons). The trouble with the view is that unless you strictly enforce the integrity of your data you are likely to lose some rows because the values in your main table have foreign key values that are invalid.</p>
<p style="margin-top: 12pt">There are a bunch of other factors, of course, which is why there is a dedicated object to solve this problem. Again, a Picklist represents a domain specific list of values that can be used to translate the key of an item (typically a foreign key in a database table) to a description.</p>
<p style="margin-top: 12pt">In the NetQuarry Platform, Picklists are of one of three distinct types:</p>
<ul style="margin-top: 0in" type="disc">
<li>A “standard” Picklist. This type of list is loaded from the metadata and supports the descriptive text in the current user’s culture (language). We use a pattern similar to the one just described to model this. (Picklist, <span>PicklistItems</span> (with a foreign key to a “Text” table to support localization))</li>
<li>A “SQL” Picklist. This type of list is loaded from one of the databases (can be the “main” operational database or the repository) and can contain 1 to 3 columns of data.</li>
<li>An “Enumeration” Picklist. This list is a 2 column Picklist loaded from a string type name that represents an Enumeration as its source. (The NetQuarry Studio makes good use of this.)</li>
<li>For the most part, Picklists tend to have the <span>LimitToList</span> attribute set. This attribute says that the item selected by the user MUST be one of the items in this list. There are several other attributes of interest as well, listed here and briefly explained:</li>
</ul>
<p> </p>
<table border="1">
<tbody>
<tr>
<td width="23%" valign="top"><strong><span>Member Name</span></strong></td>
<td width="76%" valign="top"><strong><span>Description</span></strong></td>
</tr>
<tr>
<td width="23%" valign="top"><span>Cache</span></td>
<td width="76%" valign="top"><span>This list should be cached.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>HasDiscrim</span></td>
<td width="76%" valign="top"><span>This list uses a discriminator to break items into sets.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>LimitToList</span></td>
<td width="76%" valign="top"><span>This list has at least 2 columns and the values must come from the list.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>HideUnknownItems</span></td>
<td width="76%" valign="top"><span>The list should hide unknown items.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>MarkUnknownItems</span></td>
<td width="76%" valign="top"><span>The list should mark unknown items.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>StoreAltText</span></td>
<td width="76%" valign="top"><span>The list stores the item&#8221;s Alternate Key Text column in the DB and uses it as it&#8221;s </span><span>ID.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>StoreAltInt</span></td>
<td width="76%" valign="top"><span>The list stores the item&#8221;s Alternate Key </span><span>Int</span> column in the DB and uses it as it&#8221;s <span>ID.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>StoreItemName</span></td>
<td width="76%" valign="top"><span>The list stores the item&#8221;s Name column in the DB and uses it as it&#8221;s </span><span>ID.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>NoNullEntry</span></td>
<td width="76%" valign="top"><span>The list does not need to provide a null entry.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>SortByText</span></td>
<td width="76%" valign="top"><span>List should be sorted by the display text.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>SortDesc</span></td>
<td width="76%" valign="top"><span>List should be sorted in DESC order. (Standard Picklists only)</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>SortByKey</span></td>
<td width="76%" valign="top"><span>List should be sorted by the stored key.</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>AllowUserAdd</span></td>
<td width="76%" valign="top"><span>Users can add new items to this list (providing they have Configuration permission).</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>AllowUserDelete</span></td>
<td width="76%" valign="top"><span>Users can remove items from this list (providing they have Configuration permission).</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>AllowUserUpdate</span></td>
<td width="76%" valign="top"><span>Users can update items in this list (providing they have Configuration permission).</span></td>
</tr>
<tr>
<td width="23%" valign="top"><span>Disabled</span></td>
<td width="76%" valign="top"><span>The </span><span>picklist</span> is disabled.</td>
</tr>
<tr>
<td width="23%" valign="top"><span>IgnoreWhitespace</span></td>
<td width="76%" valign="top"><span>Ignore leading and trailing whitespace when matching values.</span></td>
</tr>
</tbody>
</table>
<div>&nbsp;</div>
]]></content:encoded>
			<wfw:commentRss>http://www.netquarry.com/index.php/2006/03/picklists-1050/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
