<?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"
	>

<channel>
	<title>Nikolay Pavlov</title>
	<atom:link href="http://npavlov.kodar.net/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://npavlov.kodar.net/blog</link>
	<description>A blog about the rocky path of programming, and software engineering</description>
	<pubDate>Mon, 14 Dec 2009 09:08:20 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5</generator>
	<language>en</language>
			<item>
		<title>Wicked Number Formatting in T-SQL</title>
		<link>http://npavlov.kodar.net/blog/?p=41</link>
		<comments>http://npavlov.kodar.net/blog/?p=41#comments</comments>
		<pubDate>Thu, 12 Nov 2009 14:17:06 +0000</pubDate>
		<dc:creator>Nik</dc:creator>
		
		<category><![CDATA[Database &amp; SQL]]></category>

		<category><![CDATA[Format numbers]]></category>

		<category><![CDATA[SQL Server]]></category>

		<category><![CDATA[T-SQL]]></category>

		<guid isPermaLink="false">http://npavlov.kodar.net/blog/?p=41</guid>
		<description><![CDATA[One thing you are actually not supposed to do is to format your data in the database.  Databases are to store and manage data, and presentation is for the UI layer.
Life has its funny ways to make you do things which you should not under normal cirumstances, things which you have sworn by yourself not [...]]]></description>
			<content:encoded><![CDATA[<p>One thing you are actually not supposed to do is to format your data in the database.  Databases are to store and manage data, and presentation is for the UI layer.</p>
<p>Life has its funny ways to make you do things which you should not under normal cirumstances, things which you have sworn by yourself not to.  I came to a situation where I needed to format a <strong>money</strong> number following <strong>&#8220;#,.####&#8221;</strong> within the body of a T-SQL stored  procedure.  I simply had to do it there.  The requirement came in a very late moment of the testing phase, when moving this part out was definitely not feasible, considering the approaching deadline.</p>
<p>T-SQL has some limited functions to format data into string.  In reference to numbers - <strong>float</strong> and <strong>money</strong>, you can use <strong>CONVERT</strong>.  For <strong>float</strong>, there is no sensible option for <strong>&#8216;#,.####</strong>&#8216;.  For <strong>money</strong>, <strong>CONVERT</strong> gives three options:</p>
<table style="BACKGROUND-COLOR: #cccccc" border="1" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td><strong>0</strong> (default)</td>
<td>No commas every three digits to the left of the decimal point, and two digits to the right of the decimal point; for example, 4235.98.</td>
</tr>
<tr>
<td><strong>1</strong></td>
<td>Commas every three digits to the left of the decimal point, and two digits to the right of the decimal point; for example, 3,510.92.</td>
</tr>
<tr>
<td><strong>2</strong></td>
<td>No commas every three digits to the left of the decimal point, and four digits to the right of the decimal point; for example, 4235.9819.</td>
</tr>
</tbody>
</table>
<p>As you can see, <strong>&#8216;#,.####&#8217;</strong> is a mix of 1 and 2.</p>
<p>Poor man is devil, Bulgarians say.  What I did was to get the string, result of <strong>CONVERT</strong> with style 1, and concatenate it with the last two characters of the string, result of <strong>CONVERT</strong> with style 2:</p>
<textarea name="code" class="sql:nocontrols:nogutter" cols="60" rows="10">
CONVERT (VARCHAR, @value, 1) + RIGHT (CONVERT (VARCHAR, @value, 2), 2)  
</textarea>
<div></div>
<p><span style="color: #000000;"></p>
<table style="background-color: #ffe4c4; border: #000000 0px solid;" border="0">
<tbody>
<tr>
<td>UPDATE : 14th December 2009</td>
</tr>
</tbody>
</table>
<p> </p>
<p></span></p>
<p>There is a bug in the above code, which produces wrong result in case the last two digits are greater than 49.  The correct solution would be:</p>
<textarea name="code" class="sql:nocontrols:nogutter" cols="60" rows="10">
SET @str_value_one = CONVERT (VARCHAR, @value, 1)
SET @result = LEFT (@str_value_one, LEN (@str_value_one) - 2) +
   RIGHT (CONVERT (VARCHAR, @value, 2), 4)  
</textarea>
]]></content:encoded>
			<wfw:commentRss>http://npavlov.kodar.net/blog/?feed=rss2&amp;p=41</wfw:commentRss>
		</item>
		<item>
		<title>Google is making us stupid</title>
		<link>http://npavlov.kodar.net/blog/?p=39</link>
		<comments>http://npavlov.kodar.net/blog/?p=39#comments</comments>
		<pubDate>Mon, 24 Aug 2009 08:42:14 +0000</pubDate>
		<dc:creator>Nik</dc:creator>
		
		<category><![CDATA[Just Thoughts]]></category>

		<guid isPermaLink="false">http://npavlov.kodar.net/blog/?p=39</guid>
		<description><![CDATA[More often than not, when confronted with a problem, software developers rush to www.google.com, and start searching for samples and ready-to-use pieces of code.  The actual documentation of the language / framework / tool / whatever is often left untouched.  Google&#8217;s highly efficient search engine is really good in finding the best answer, much more relevant than [...]]]></description>
			<content:encoded><![CDATA[<p>More often than not, when confronted with a problem, software developers rush to <a href="http://www.google.com" onclick="javascript:pageTracker._trackPageview ('/outbound/www.google.com');">www.google.com</a>, and start searching for samples and ready-to-use pieces of code.  The actual documentation of the language / framework / tool / whatever is often left untouched.  Google&#8217;s highly efficient search engine is really good in finding the best answer, much more relevant than the results of the built-in searching facilities of the documentation in question.  Plus, it reveals others&#8217; experience.</p>
<p>As good as it gets, using Google too much has a dark side.  Developers often come to the point when they implement solutions with technologies they do not understand.  They are not troubled by the fact that they use code, written by someone else, and which they don&#8217;t understand.  If they run into a trouble with the sample solution they found, they will go to various forums to find a fix.  An old joke about how to write an algorithm to find a lion in the desert and lock it in a cage had it for Delphi that Delphi developers would go to all known forums and post &#8220;Does anyone have a component which finds a lion in the desert and locks it in a cage?&#8221;.  Well, I am sorry to inform you, smart Delph-haters out there, that is no longer a Delphi-thing only.  You all fell into the trap.</p>
<p>To be honest, that particular approach works quite often, and it works well.  Why am I making fuss about it, then?  Development goes with good speed, results are often nice.  Until the moment when Google doesn&#8217;t give an answer.  Or, to be presice, its answer is incomprehensible, because the developer has no understanding of the technologies involves whatsoever. </p>
<p>The ease with which solutions are found in Google takes away the incentive to get into real understanding of how things actually work.  As a result, junior developers stay junior, and never learn basics which will take them to a higher level of skills.</p>
<p>That is the reason why I am no longer eager to give code samples.  People would never read them, just copy &amp; paste it and even ask specific questions how to integrate them into their own code. I prefer explaining things, and give out only snippets of important code.  Who claims to be a developer should be capable of figuring the rest by oneself.</p>
]]></content:encoded>
			<wfw:commentRss>http://npavlov.kodar.net/blog/?feed=rss2&amp;p=39</wfw:commentRss>
		</item>
		<item>
		<title>SQL Server: Shrink Database Log, Part II</title>
		<link>http://npavlov.kodar.net/blog/?p=38</link>
		<comments>http://npavlov.kodar.net/blog/?p=38#comments</comments>
		<pubDate>Mon, 13 Jul 2009 07:47:48 +0000</pubDate>
		<dc:creator>Nik</dc:creator>
		
		<category><![CDATA[Database &amp; SQL]]></category>

		<guid isPermaLink="false">http://npavlov.kodar.net/blog/?p=38</guid>
		<description><![CDATA[Here is another approach to shrink an extensively large MS SQL Server log file:

ALTER DATABASE Northwind

SET RECOVERY SIMPLE;

GO

-- Shrink the truncated log file to 1 MB.

DBCC SHRINKFILE ('Northwind_Log', 100);

GO

-- Reset the database recovery model.

ALTER DATABASE RHClient

SET RECOVERY FULL;

GO

Thanks to  Stilgar for helping me out with this one.
]]></description>
			<content:encoded><![CDATA[<p>Here is another approach to shrink an <a href="http://npavlov.kodar.net/blog/?p=36">extensively large MS SQL Server log file</a>:</p>
<textarea name="code" class="sql:nocontrols:nogutter" cols="60" rows="10">
ALTER DATABASE Northwind

SET RECOVERY SIMPLE;

GO

-- Shrink the truncated log file to 1 MB.

DBCC SHRINKFILE ('Northwind_Log', 100);

GO

-- Reset the database recovery model.

ALTER DATABASE RHClient

SET RECOVERY FULL;

GO
</textarea>
<p>Thanks to  <a href="http://www.sietch.net/" onclick="javascript:pageTracker._trackPageview ('/outbound/www.sietch.net');">Stilgar </a>for helping me out with this one.</p>
]]></content:encoded>
			<wfw:commentRss>http://npavlov.kodar.net/blog/?feed=rss2&amp;p=38</wfw:commentRss>
		</item>
		<item>
		<title>SQL Server: Shrink Database Log</title>
		<link>http://npavlov.kodar.net/blog/?p=37</link>
		<comments>http://npavlov.kodar.net/blog/?p=37#comments</comments>
		<pubDate>Tue, 07 Jul 2009 10:40:12 +0000</pubDate>
		<dc:creator>Nik</dc:creator>
		
		<category><![CDATA[Database &amp; SQL]]></category>

		<guid isPermaLink="false">http://npavlov.kodar.net/blog/?p=37</guid>
		<description><![CDATA[In Microsoft SQL Server sometimes you can observe the LOG file growing uncontrollably and unexpectedly to a size times the size of the DATA file.  I&#8217;ve witnessed  a database with data file of 200 MB and a log file of 4 GB.  Not only harddisk space is wasted, but the backup file becomes too inconvenient to [...]]]></description>
			<content:encoded><![CDATA[<p>In Microsoft SQL Server sometimes you can observe the LOG file growing uncontrollably and unexpectedly to a size times the size of the DATA file.  I&#8217;ve witnessed  a database with data file of 200 MB and a log file of 4 GB.  Not only harddisk space is wasted, but the backup file becomes too inconvenient to drag around even heavily compressed.</p>
<p>Why does the LOG file grow that much is a different story, which I am not prepared to tell now.  The question is how to make the LOG file small again within the &#8220;normal&#8221; boundaries.  Using the &#8220;Shrink database&#8221; command does no good.  Backup and restore of the database gives you the same old large log file.</p>
<p>The only solution I know so far involves the following steps:</p>
<ol>
<li>Create a new, empty database.</li>
<li>Script all the db structure, and use it to create an identical copy of your old one into the new database you just created.</li>
<li>Use bulk copy to transfer all data from the original database to the new one.</li>
</ol>
<p>Voila, the LOG file is back to normal.</p>
<p>Note that you might need to disable certain triggers and foreign keys before the copy operations - that depends completely on your database.</p>
]]></content:encoded>
			<wfw:commentRss>http://npavlov.kodar.net/blog/?feed=rss2&amp;p=37</wfw:commentRss>
		</item>
		<item>
		<title>Coding Horrors: MySQL, Dates and Times</title>
		<link>http://npavlov.kodar.net/blog/?p=36</link>
		<comments>http://npavlov.kodar.net/blog/?p=36#comments</comments>
		<pubDate>Wed, 27 May 2009 11:44:52 +0000</pubDate>
		<dc:creator>Nik</dc:creator>
		
		<category><![CDATA[Database &amp; SQL]]></category>

		<category><![CDATA[Just Thoughts]]></category>

		<guid isPermaLink="false">http://npavlov.kodar.net/blog/?p=36</guid>
		<description><![CDATA[An excerpt from MySQL Reference Manual:
Illegal DATETIME, DATE, or TIMESTAMP values are converted to the &#8220;zero&#8221; value of the appropriate type (&#8217;0000-00-00 00:00:00&#8242; or &#8216;0000-00-00&#8242;). 
What the fuck.  Really, come on.  The purpose of a database is to store valid and integral data.  Again.  Valid.  And.  Integral.  Data.  It is valid, integral and meaningful that counts.  [...]]]></description>
			<content:encoded><![CDATA[<p class="comments">An excerpt from <a href="http://dev.mysql.com/doc/refman/6.0/en/datetime.html" onclick="javascript:pageTracker._trackPageview ('/outbound/dev.mysql.com');">MySQL Reference Manual</a>:</p>
<blockquote><p><cite>Illegal DATETIME, DATE, or TIMESTAMP values are converted to the &#8220;zero&#8221; value of the appropriate type (&#8217;0000-00-00 00:00:00&#8242; or &#8216;0000-00-00&#8242;). </cite></p></blockquote>
<p>What the fuck.  Really, come on.  The purpose of a database is to store<em> valid and integral data</em>.  Again.  <strong>Valid.  And.  Integral.  Data.</strong>  It is valid, integral and meaningful that counts.  Not just any rubbish.  If I want rubbish, I can just read back random bytes from the harddisk.  If someone tries to write crap into a database, which the database cannot handle, the database <em>must</em> refuse the operation, and give error. </p>
<p>Really, I wonder what the hell designers of MySQL were thinking when they implemented this specific feature.  Pardon me, the word &#8220;feature&#8221; is not appropriate.  The correct word would be &#8220;disaster&#8221;.  It is a disaster indeed, because it silently causes data loss.  One might argue that it is developers&#8217; responsibility to validate their data, and make sure they provide the database with valid input.  While this is definitely true, it is no excuse for the database to accept graciously any garbage, and on top of that convert it to something which has nothing to do with what it is supposed to be.  That is a major fail in design, and major fail to achieve a primary goal.</p>
<p>The behavior above is true for MySQL versions from 4.1 to 6.0.</p>
<p>This little story only proves that MySQL is only good as a backend for small and simple websites.  If you mean serious business, please reconsider.  There are a bunch of free databases out there, all of them much, much better and more mature.  Some of them even open source.</p>
<p>And yes, I know there is a general setting in MySQL 5.02 and greater to make it give errors.  And yes, I don&#8217;t think it makes the fail lesser.</p>
]]></content:encoded>
			<wfw:commentRss>http://npavlov.kodar.net/blog/?feed=rss2&amp;p=36</wfw:commentRss>
		</item>
		<item>
		<title>Rant: Moving Targets</title>
		<link>http://npavlov.kodar.net/blog/?p=35</link>
		<comments>http://npavlov.kodar.net/blog/?p=35#comments</comments>
		<pubDate>Mon, 25 May 2009 08:34:00 +0000</pubDate>
		<dc:creator>Nik</dc:creator>
		
		<category><![CDATA[Architecture]]></category>

		<category><![CDATA[Just Thoughts]]></category>

		<guid isPermaLink="false">http://npavlov.kodar.net/blog/?p=35</guid>
		<description><![CDATA[A trip back in time.  In 2000 we were starting a large project.  The architecture was pretty standard stuff – database server, application server with business objects, semi-thin desktop client, featuring bi-directional communication between the clients and the server.  All were Windows native applications.  During the design phase the question about the inter-tier communication technology [...]]]></description>
			<content:encoded><![CDATA[<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span style="font-family: Calibri; font-size: small;">A trip back in time.  In 2000 we were starting a large project.<span style="mso-spacerun: yes">  </span>The architecture was pretty standard stuff – database server, application server with business objects, semi-thin desktop client, featuring bi-directional communication between the clients and the server.<span style="mso-spacerun: yes">  </span>All were Windows native applications.<span style="mso-spacerun: yes">  </span>During the design phase the question about the inter-tier communication technology came up.<span style="mso-spacerun: yes">  </span>Back then, <a href="http://msdn.microsoft.com/en-us/library/bb263931%28VS.85%29.aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/msdn.microsoft.com');">Windows DNA</a><sup>1</sup> was the super-dee-duper stuff out there, praised by Microsoft as the prime guide to making distributed applications.<span style="mso-spacerun: yes">  </span>We decided to follow its wisdom, and built the communication layer on top of Distributed COM and COM+.  Oh, why, why?</span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span id="more-35"></span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span style="font-family: Calibri; font-size: small;">I have huge respect for COM as a technology, and within a single workstation it is a wonderful instrument for application interoperability and extensibility.<span style="mso-spacerun: yes">  </span>However, when you stick your head out in the outer world, things get tough.<span style="mso-spacerun: yes">  </span>Every weathered COM developer will tell you what a nightmare it is to setup and configure DCOM in a local network.<span style="mso-spacerun: yes">  </span>Yes, once configured properly, it is solid.<span style="mso-spacerun: yes">  </span>But that is only when you configure it.<span style="mso-spacerun: yes">  </span>God forbid you have to setup DCOM in a network without Active Directory.<span style="mso-spacerun: yes">  Even with AD, doing DCOM callbacks is as pleasant as a trip in a swamp, plagued by mosquitos and crocodiles.  </span>DCOM over the Internet?<span style="mso-spacerun: yes">  </span>Please.<span style="mso-spacerun: yes">  </span>That works only in Microsoft papers from late 90s, when the Internet was not plagued by hackers, worms and trojans, and there was little need for firewalls.</span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span style="font-family: Calibri; font-size: small;">By 2005 the product was successful and the number of installations was increasing, and we found ourselves wondering how the hell to get rid of COM, and replace it with something as high-performing, but easy to deploy.<span style="mso-spacerun: yes">  </span>Before you start giving bright ideas about the next hot shit on the block – Java RMI, NET Remoting, web-services, just think about the hundreds of thousands lines of native Win32 code we simply had to preserve.<span style="mso-spacerun: yes">  </span>We needed something that would plug in with minimal changes in the existing code base.</span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span style="font-family: Calibri; font-size: small;">This time we approached the problem very carefully and full of suspicions about every new thing out there.<span style="mso-spacerun: yes">  </span>Rumors already had it that Remoting was not as hot as it seemed at first, and its abilities for bi-directional communications were more trouble that real use.<span style="mso-spacerun: yes">  </span>Microsoft was already murmuring about the next hottest thing – WCF, which was supposed to solve all communication problems again.<span style="mso-spacerun: yes">  </span>Yeah, right.</span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span style="font-family: Calibri; font-size: small;">We considered really many things, including .NET Framework.<span style="mso-spacerun: yes">  </span>We designed a dozen of bridge applications, only to scrap them all.<span style="mso-spacerun: yes">  </span>Our analysis indentified that the types of data we were transferring were standard types as integer, float and string, ADO Recordsets, and Variants.<span style="mso-spacerun: yes">  </span>And the server-to-client communication, of course, that was supposed to work even for clients behind firewalls.<span style="mso-spacerun: yes">  </span>The common types are trivial to marshal across a network with any technology out there.<span style="mso-spacerun: yes">  </span>The other two are sweet with COM.<span style="mso-spacerun: yes">  </span>Marshalling ADO Recordsets is not that hard actually, because ADO can save and load recordsets to streams.<span style="mso-spacerun: yes">  </span>Sweet.<span style="mso-spacerun: yes">  </span>Marshalling Variants is a bigger issue, as COM keeps this part strictly undocumented.<span style="mso-spacerun: yes">  </span>However, we <a href="http://npavlov.kodar.net/blog/?p=11">managed to do that</a>, too.</span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span style="font-family: Calibri; font-size: small;">Having achieved that, we made our decision.<span style="mso-spacerun: yes">  </span>We implemented our own RPC protocol, based on TCP/IP.<span style="mso-spacerun: yes">  </span>It was capable of marshalling all necessary data types, and supported bi-directional communications through firewalls.</span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span style="font-family: Calibri; font-size: small;">The DNA-&gt;Remoting-&gt;WS-&gt;WCF technology transition is not the only one in the world.<span style="mso-spacerun: yes">  </span>Sun Java also adopted web services and kind of forgot about RMI.<span style="mso-spacerun: yes">  </span>Microsoft recently made it clear that WinForms will be retired with honors to give way to WPF.</span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span style="font-family: Calibri; font-size: small;">Technology is dynamic, and so is the world.<span style="mso-spacerun: yes">  </span>I do not blame Microsoft, neither anyone else.<span style="mso-spacerun: yes">  </span>The price of progress is the low long-term value of moment achievements.</span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span style="font-family: Calibri; font-size: small;">The moral of the story is: never, ever trust newest technologies as the best cure for all problems.<span style="mso-spacerun: yes">  </span>Always test them against your case.<span style="mso-spacerun: yes">  </span>And, sometimes, you’d better do it your own way.<span style="mso-spacerun: yes">  </span>More often than not the investment is worthy.</span></span></p>
<p class="MsoNormal" style="MARGIN: 0cm 0cm 10pt"><span lang="EN-US"><span style="font-family: Calibri;"><span style="font-size: x-small;">1. There is no more a homepage for Windows DNA.  </span><a href="http://www.microsoft.com/dna" onclick="javascript:pageTracker._trackPageview ('/outbound/www.microsoft.com');"><span style="font-size: x-small;">www.microsoft.com/dna</span></a><span style="font-size: x-small;"> quitely forwards you to NET Framework.</span></span></span></p>
]]></content:encoded>
			<wfw:commentRss>http://npavlov.kodar.net/blog/?feed=rss2&amp;p=35</wfw:commentRss>
		</item>
		<item>
		<title>Virtual ListViews - Name for Speed</title>
		<link>http://npavlov.kodar.net/blog/?p=22</link>
		<comments>http://npavlov.kodar.net/blog/?p=22#comments</comments>
		<pubDate>Fri, 10 Apr 2009 08:43:48 +0000</pubDate>
		<dc:creator>Nik</dc:creator>
		
		<category><![CDATA[NET]]></category>

		<category><![CDATA[Win32]]></category>

		<guid isPermaLink="false">http://npavlov.kodar.net/blog/?p=22</guid>
		<description><![CDATA[ListView.  Huh?  Come on, you all know it - the right pane of Windows Explorer.  That is, where contents of folders are displayed.  Whenever you see large icons, or small items listed in columns, or a list of items with details in other columns, it is always one and the same control - ListView.  Kind [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://msdn.microsoft.com/en-us/library/bb774735(VS.85).aspx" onclick="javascript:pageTracker._trackPageview ('/outbound/msdn.microsoft.com');">ListView</a>.  Huh?  Come on, you all know it - the right pane of Windows Explorer.  That is, where contents of folders are displayed.  Whenever you see large icons, or small items listed in columns, or a list of items with details in other columns, it is always one and the same control - ListView.  Kind of a Listbox, but much, much better and powerful.  ListView control came into this world with Windows Explorer back in WIndows 95, and got numerous enhancements eversince.  ListView is very convenient when it comes to display a list of items.  It can even substitute grid controls for read-only data in many cases, as ListView can display multiple columns per data item.  Add support for icons, check boxes, grouping and different layouts, and you have a real beauty.  How to use ListViews is out of the scope of this post.  If you want to learn it - just google for it.  There are tons of tutorials out there.</p>
<p>Great as they are, ListView contols can be very slow with large number of items (like tens of thousands), especially while populating with data.  Furthermore, by default ListView stores all its items internally.  In case you populate the List View from an in-memory collection, you end up with doubled memory usage.  Another thing to be worried about when working with tons of data.</p>
<p>The solution to both the performance and memory-usage issues is to use <a href="http://msdn.microsoft.com/en-us/library/bb774735(VS.85).aspx#Virtual_ListView_Style" onclick="javascript:pageTracker._trackPageview ('/outbound/msdn.microsoft.com');">Virtual ListViews</a>.</p>
<p><span id="more-22"></span></p>
<p>In this article I will not go into details about how to use virual list views in a generic Win32 application.  I will make my examples in Windows Forms.  Win32 and Delphi fans, do stay disappointed.  There is nothing actually different in using Virtual ListViews in any platform.  You either respond to messages (Win32 fashion), or attach to events (Delphi and NET).  Anyways, you are expected to do basically the same thing.</p>
<p>ListView controls support a special operating mode - virtual mode.  In this mode, the list view control does not store the items it displays internally.  In fact, it only stores the number of items it contains, and nothing else.  Then, when it needs to display an item, it simply sends a message to its parent window to provide the actual data of the item - caption, columns, icon index.  As a result, the listview doesn&#8217;t consume any memory, and it is very fast to initialize it - you simply don&#8217;t populate it with data.</p>
<p>To make a ListView control virtual, set property <strong>VirtualMode</strong> to <strong>true</strong>, and set proprery <strong>VirtualListSize</strong> to the number of elements in your collection with data.</p>
<p>The minimal functionality you have to provide is to add an event handler to LisiView&#8217;s <strong>RetrieveVirtualItem</strong> event.  A simple code would go something like this:</p>
<textarea name="code" class="c#:nocontrols:nogutter" cols="60" rows="10">
private void listView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
  MyDataClassitem = data[e.ItemIndex];
  e.Item = new ListViewItem (new string[2] { item.Title, item.Description });
}
</textarea>
<p>Though being clearly obvious, let me explain.  <strong>MyDataClass</strong> is a custom class I defined, which happens to have two properties of type <strong>String</strong> - Title and Description.  Of course, you are not limited or required to have such; you can have anything you need.  <strong>data</strong> is a collection of my data  (I can&#8217;t believe I typed this, but my experience at the university taught me better).</p>
<p>Basically, you are done. </p>
<p>Virtual ListViews are even more powerful than that.  You can cache your data for improved performance, and handle extra events to support searching.  If I got you interested, just take a look at <a href="http://msdn.microsoft.com/en-us/library/bb774735(VS.85).aspx#Virtual_ListView_Style" onclick="javascript:pageTracker._trackPageview ('/outbound/msdn.microsoft.com');">MSDN</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://npavlov.kodar.net/blog/?feed=rss2&amp;p=22</wfw:commentRss>
		</item>
		<item>
		<title>Coding Horrors: C++ and Overloaded Methods</title>
		<link>http://npavlov.kodar.net/blog/?p=34</link>
		<comments>http://npavlov.kodar.net/blog/?p=34#comments</comments>
		<pubDate>Thu, 09 Apr 2009 11:12:47 +0000</pubDate>
		<dc:creator>Nik</dc:creator>
		
		<category><![CDATA[Just Thoughts]]></category>

		<guid isPermaLink="false">http://npavlov.kodar.net/blog/?p=34</guid>
		<description><![CDATA[My tough feelings for C++ as a language are all but new.  Here is another example why this language is not suited for children, and young students should not take C++ as their first programming language, unless they are really smart and have solid common sense to protect them from the bad influence of this language.
Consider the [...]]]></description>
			<content:encoded><![CDATA[<p>My tough feelings for C++ as a language are all but new.  Here is another example why this language is not suited for children, and young students should not take C++ as their first programming language, unless they are really smart and have solid common sense to protect them from the bad influence of this language.</p>
<p>Consider the following code:</p>
<textarea name="code" class="c:nocontrols:nogutter" cols="60" rows="10">
class String
{
public:
  String(const char*);
};

void myFunction(String, String, bool = false);
void myFunction(String, bool = false);

void main()
{
  myFunction(“Hello”, “Goodbye”);
}
</textarea>
<p>Nothing special, right?  It looks absolutely logical that the call to <strong>myFunction</strong> in <strong>main()</strong> would invoke void <strong>myFunction(String, String, bool = false)</strong>.  Well, it won&#8217;t.  The function that will get called is <strong>void myFunction(String, bool = false)</strong>.</p>
<p>Well, I must admit that I myself would not figure out easily.  Further reading revealed the explanation - the compiler is using the more cost-efficient conversion of <strong>char *</strong> to <strong>bool</strong>, rather than creating a new instance of class <strong>String</strong>.  Further reading proved that the behaviour of the compiler is strictly according to the C++ Standards!</p>
<p>Feel free to call me any names you can think of, but for me the authors of C++ Standards live in a parallel, sick universe.  Guys, have you heard that code has to be readable, too?</p>
<p>P.S. Edit: fixing typos.</p>
]]></content:encoded>
			<wfw:commentRss>http://npavlov.kodar.net/blog/?feed=rss2&amp;p=34</wfw:commentRss>
		</item>
		<item>
		<title>Select Master Records with Multiple Child Records</title>
		<link>http://npavlov.kodar.net/blog/?p=32</link>
		<comments>http://npavlov.kodar.net/blog/?p=32#comments</comments>
		<pubDate>Tue, 03 Feb 2009 09:11:14 +0000</pubDate>
		<dc:creator>Nik</dc:creator>
		
		<category><![CDATA[Database &amp; SQL]]></category>

		<guid isPermaLink="false">http://npavlov.kodar.net/blog/?p=32</guid>
		<description><![CDATA[A friend of mine asked this question:
I have two tables: table T1 with primary key field ID, and table T2 with field ID which is a foreign key to ID from T1, and field VAL.  How do I select all records from T1, for which there are records from T2 with values X and Y? 
For example, [...]]]></description>
			<content:encoded><![CDATA[<p>A friend of mine asked this question:</p>
<p>I have two tables: table T1 with primary key field ID, and table T2 with field ID which is a foreign key to ID from T1, and field VAL.  How do I select all records from T1, for which there are records from T2 with values X <strong>and</strong> Y? </p>
<p>For example, considering the following data, I want all records from T1, where exist records records from T2 with values 1 and 2.</p>
<table style="height: 141px;" border="0" width="260">
<tbody>
<tr valign="top">
<td>
<pre>T1 has records
1
2
3</pre>
</td>
<td>
<pre>T2 has records</pre>
<table style="height: 104px;" border="0" width="90">
<tbody>
<tr>
<td>
<pre>1</pre>
</td>
<td>
<pre>1</pre>
</td>
</tr>
<tr>
<td>
<pre>1</pre>
</td>
<td>
<pre>2</pre>
</td>
</tr>
<tr>
<td>
<pre>2</pre>
</td>
<td>
<pre>1</pre>
</td>
</tr>
<tr>
<td>
<pre>3</pre>
</td>
<td>
<pre>1</pre>
</td>
</tr>
<tr>
<td>
<pre>3</pre>
</td>
<td>
<pre>2</pre>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>Desired output is records 1 and 3 from table 1.</p>
<p>The question is actually interesing only if we want to select records from table T1 for which there are an arbitrary number of records with respective values in T2.</p>
<p>There are a few ways to implement this.  Here is my choice number one for an arbitrary number of values:</p>
<textarea name="code" class="sql:nocontrols:nogutter" cols="60" rows="10">
SELECT T1.ID, COUNT(T1.ID) FROM T1, T2
WHERE T1.ID = T2.ID AND T2.VAL IN (x, y, ...)
GROUP BY T1.ID
HAVING COUNT (T1.ID) = (num values)
</textarea>
<p>If we are considering a few number of values - like four or five, I would suggest an alternative, which might prove even more efficient:</p>
<textarea name="code" class="sql:nocontrols:nogutter" cols="60" rows="10">
SELECT T1.ID FROM T1, T2_1, Т2_2
WHERE
  T1.ID = T2_1.ID AND T2_1.VAL = x
  AND
  T1.ID = T2_2.ID AND T2_2.VAL = y
</textarea>
<p> </p>
<p>Providing we have a foreign key on T2.ID to T1.ID, the JOIN-approach can be really efficient. </p>
]]></content:encoded>
			<wfw:commentRss>http://npavlov.kodar.net/blog/?feed=rss2&amp;p=32</wfw:commentRss>
		</item>
		<item>
		<title>Lectures OOP w/ C#</title>
		<link>http://npavlov.kodar.net/blog/?p=31</link>
		<comments>http://npavlov.kodar.net/blog/?p=31#comments</comments>
		<pubDate>Thu, 29 Jan 2009 20:57:10 +0000</pubDate>
		<dc:creator>Nik</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://npavlov.kodar.net/blog/?p=31</guid>
		<description><![CDATA[I started teaching a course in Object-oriented programming with C# 3.0.  Here is the link to the slides of the lectures.
]]></description>
			<content:encoded><![CDATA[<p>I started teaching a course in Object-oriented programming with C# 3.0.  Here is the <a href="http://npavlov.kodar.net/oopcsharp.zip">link</a> to the slides of the lectures.</p>
]]></content:encoded>
			<wfw:commentRss>http://npavlov.kodar.net/blog/?feed=rss2&amp;p=31</wfw:commentRss>
		</item>
	</channel>
</rss>

