<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.microsoft.co.il/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>.NET Geek</title><link>http://blogs.microsoft.co.il/blogs/kim/</link><description> 
&amp;quot;It is upon the Trunk that a gentleman works&amp;quot;
- Confucius </description><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>CodeRush Plugin – Navigate to Implementation</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/11/12/coderush-plugin-navigate-to-implementation.aspx</link><pubDate>Thu, 12 Nov 2009 21:23:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:442967</guid><dc:creator>Kim</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=442967</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/11/12/coderush-plugin-navigate-to-implementation.aspx#comments</comments><description>&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; As of version 9.3.2 of CodeRush&amp;nbsp;functionality similiar to that provided by this plugin is provided in the core product and support and builds for this plugin is discontinued... If you need assistance for earlier version of CR, just leave a comment and I&amp;#39;ll get back to you.&lt;/p&gt;
&lt;p&gt;Instead of posting a new a post every time a new build of CodeRush (and the plugin) becomes available, I’ll start to post the binaries here by updating this post. If you are interested in the source code, you can get it &lt;a href="http://dxcorecommunityplugins.googlecode.com/svn/trunk/CR_NavigationContrib"&gt;here&lt;/a&gt;. If you want a walk-through of how the plugin was built, you can find the first post in a series &lt;a href="http://blogs.microsoft.co.il/blogs/kim/archive/2008/10/19/coderush-plugin-navigate-to-implementation-part-1.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/WindowsLiveWriter/CodeRushPluginNavigatetoImplementationPa_98A0/image_4.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;MARGIN-LEFT:0px;BORDER-LEFT-WIDTH:0px;MARGIN-RIGHT:0px;" title="image_4[1]" border="0" alt="image_4[1]" align="left" src="http://blogs.microsoft.co.il/blogs/kim/image_41_28DE5888.png" width="482" height="565" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Plugin binaries built against CodeRush version:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/CRNavContrib/Navigate2Impl%20CR%209.2.4.zip"&gt;9.2.4&lt;/a&gt; &lt;br /&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/CRNavContrib/Navigate2Impl%20CR%209.2.8.zip"&gt;9.2.8&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/CRNavContrib/Navigate2Impl%20CR%209.2.9.zip"&gt;9.2.9&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;To install the plugin copy the binaries to: C:\Users\{your user name}\Documents\DevExpress\IDE Tools\Community\PlugIns&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=442967" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/CodeRush/default.aspx">CodeRush</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Plugin/default.aspx">Plugin</category></item><item><title>Calling the Google Closure Javascript Compiler - Code</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/11/10/calling-the-google-closure-javascript-compiler-code.aspx</link><pubDate>Tue, 10 Nov 2009 20:38:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:441175</guid><dc:creator>Kim</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=441175</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/11/10/calling-the-google-closure-javascript-compiler-code.aspx#comments</comments><description>&lt;p&gt;Here’s a follow-up to the &lt;a href="http://blogs.microsoft.co.il/blogs/kim/archive/2009/11/08/integrating-google-javascript-compiler-in-visual-studio.aspx"&gt;last post&lt;/a&gt; that contained a few screenshots showing the integration of the Google Closure Javascript compiler in Visual Studio. &lt;/p&gt;
&lt;p&gt;Since I said in the last post that I would make the source available if there was interest, I’m doing that now.&lt;/p&gt;
&lt;p&gt;The project structure is as following&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/solutionstruct_376A6371.jpg"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="solution struct" border="0" alt="solution struct" src="http://blogs.microsoft.co.il/blogs/kim/solutionstruct_thumb_59FE7C1F.jpg" width="231" height="513" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;All of the code for accessing the compilation service is in the GoogleClosure project. Initially I didn’t have a Winform project. I split the projects for this post, realizing that some people interested in the code might not have CodeRush.&lt;/p&gt;
&lt;p&gt;The GoogleClosure project also contains the UI in a user control. As such, there was no code to be written in neither the VS plugin or in the Winform application. Placing the user control from the GoogleClosure project is enough.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;About the code:&lt;/strong&gt; The code was written in brain-storming mode. As such, I won’t stand to trial for any best-practice not followed or any shortcut taken. ;-) &lt;br /&gt;Seriously though, there’s not a lot of code here. In essence, the Compilation namespace in the GoogleClosure project, contains classes that maps to the compiler service results and options. The ClosureCompilerService class is doing all the communcation with the service. The compiler service can return its results in XML, JSON and text. I implemented only parsing of the XML results which is simple in .Net using Linq2Xml.&lt;/p&gt;
&lt;p&gt;P.S (The “CR_” naming convention is common for CodeRush plugins.) &lt;br /&gt;&lt;/p&gt;
&lt;p&gt;You can download the source code &lt;a href="http://blogs.microsoft.co.il/blogs/kim/ClosureJs.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://dotnetshoutout.com/Calling-the-Google-Closure-Javascript-Compiler-Code-NET-Geek"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;BORDER-TOP:0px;BORDER-RIGHT:0px;" alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3A%2F%2Fblogs.microsoft.co.il%2Fblogs%2Fkim%2Farchive%2F2009%2F11%2F10%2Fcalling-the-google-closure-javascript-compiler-code.aspx" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=441175" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/CodeRush/default.aspx">CodeRush</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Plugin/default.aspx">Plugin</category></item><item><title>Integrating Google Javascript Compiler in Visual Studio</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/11/08/integrating-google-javascript-compiler-in-visual-studio.aspx</link><pubDate>Sun, 08 Nov 2009 21:56:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:440254</guid><dc:creator>Kim</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=440254</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/11/08/integrating-google-javascript-compiler-in-visual-studio.aspx#comments</comments><description>&lt;p&gt;Friday, &lt;a href="http://ajaxian.com/archives/google-releases-closure-the-tools-behind-the-js-geniuses"&gt;Google released&lt;/a&gt; some of their Javascript tools. Among them the Closure Javascript compiler. Being excited that Google has released Closure (the compiler), I decided to give it a go. So late Saturday night after the party was over and the kids were sleeping, I played a little with the &lt;a href="http://closure-compiler.appspot.com/home"&gt;online UI&lt;/a&gt; when I saw that the compiler services are exposed through a REST web service. At that point it would be a crime to go to sleep.&lt;/p&gt;
&lt;p&gt;2 hours later…&lt;/p&gt;
&lt;p&gt;In this screenshot you can see some compiler statistics. (Yes, you can use the compiler service as a pretty-printer or minifier)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/stats_2700ADBB.jpg"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;" title="stats" border="0" alt="stats" src="http://blogs.microsoft.co.il/blogs/kim/stats_thumb_59C08E62.jpg" width="856" height="977" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Dubious code is flagged with warnings. (I like the “Is there a bug?” message)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/warning_724005E5.jpg"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;" title="warning" border="0" alt="warning" src="http://blogs.microsoft.co.il/blogs/kim/warning_thumb_684AEEAD.jpg" width="1028" height="735" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;If you get the script plain wrong, you’ll be greeted with an error.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/error_2151A5E3.jpg"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;" title="error" border="0" alt="error" src="http://blogs.microsoft.co.il/blogs/kim/error_thumb_57DF5127.jpg" width="1028" height="323" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;I love the fact that it is possible to whip up something like this in just a couple of hours. &lt;/p&gt;
&lt;p&gt;The Visual Studio Integration was built as a CodeRush plugin (which takes a full 5 minutes). The rest of the time was spent reading the Closure web service spec and parsing the results from the web service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It’s not all good however.&lt;/strong&gt; In the current implementation you need to copy the source from the editor to the code pane in the tool window which isn’t a great user experience. Also, there’s no easy way to “jump” to the error location when there is a warning or an error. There is also no UI for setting the compiler options.&lt;/p&gt;
&lt;p&gt;Future Plans: (Maybe)&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Compile the enclosing scope under the caret by pressing a key combination.&lt;/li&gt;
&lt;li&gt;Integrate with Visual Studio Error tool window. (I have no idea how to do that)&lt;/li&gt;
&lt;li&gt;Expose the compiler options through an option page. (Currently I use some decent defaults)&lt;/li&gt;
&lt;li&gt;Any other ideas?&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;If there’s interest, I’m considering writing up a small series of how the plugin was built including source and binaries. (It’s small enough that it won’t take all my spare time)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://dotnetshoutout.com/Integrating-Google-Javascript-Compiler-in-Visual-Studio-NET-Geek"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;BORDER-TOP:0px;BORDER-RIGHT:0px;" alt="Shout it" src="http://dotnetshoutout.com/image.axd?url=http%3A%2F%2Fblogs.microsoft.co.il%2Fblogs%2Fkim%2Farchive%2F2009%2F11%2F08%2Fintegrating-google-javascript-compiler-in-visual-studio.aspx" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt;&amp;nbsp;Code can be found here -&amp;nbsp;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/archive/2009/11/10/calling-the-google-closure-javascript-compiler-code.aspx"&gt;http://blogs.microsoft.co.il/blogs/kim/archive/2009/11/10/calling-the-google-closure-javascript-compiler-code.aspx&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=440254" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Code+Editor/default.aspx">Code Editor</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/CodeRush/default.aspx">CodeRush</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Plugin/default.aspx">Plugin</category></item><item><title>My Favorite SQL Server 2k8 Feature</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/10/22/my-favorite-sql-server-2k8-feature.aspx</link><pubDate>Fri, 23 Oct 2009 02:31:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:429409</guid><dc:creator>Kim</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=429409</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/10/22/my-favorite-sql-server-2k8-feature.aspx#comments</comments><description>&lt;p&gt;Since I&amp;#39;m typing this on my new Eee 1101HA I&amp;#39;m going to keep it short. (I hate these mini keyboards)&lt;/p&gt;
&lt;p&gt;Keeping an eye on our production Sql Server box is an integral part of my daily routine. I would not categorize myself as a DBA as I don&amp;#39;t do much administrative work related to our databases. I&amp;#39;m dealing mainly with issues that are related to development and making sure our system runs efficiently. One of those tasks is to make sure that our database is properly indexed and maintaining&amp;nbsp;indexes&amp;nbsp;as the database grows. Anyone who has done any significant work against a database knows the importance of proper indexing and that proper indexing is a balancing act. &lt;br /&gt;Clustered, non clustered, covering, fill factors and page splits are just a tiny subset of the things that you have to keep on top of. &lt;/p&gt;
&lt;p&gt;My absolute favorite feature in Sql Server 2008 is &lt;strong&gt;filtered indexes&lt;/strong&gt;. In a nutshell you create an index with a filter which is used to determine what goes into the index and what not. &lt;br /&gt;Let&amp;#39;s say you have a table with some bit flags. The selectivity on these columns&amp;nbsp;might be&amp;nbsp;too low to be of any real use for even the smartest query analyzer and you&amp;#39;ll often see&amp;nbsp;scans when filtering on these bit flags. &lt;br /&gt;In some of our&amp;nbsp;tables we have bit flags where the vast majority of the records have&amp;nbsp;these bit flags set to false. In these scenarios filtered indexes just shine. After creating a filtered index on only the true values of the bit flag we had queries that would take minutes to execute drop to a few milliseconds. &lt;/p&gt;
&lt;p&gt;For more information and some important&amp;nbsp;issues related to maintaining filtered indexes,&amp;nbsp;you should check out the following excellent posts. &lt;br /&gt;&lt;a href="http://www.sqlskills.com/BLOGS/KIMBERLY/post/Filtered-indexes-and-filtered-stats-might-become-seriously-out-of-date.aspx"&gt;http://www.sqlskills.com/BLOGS/KIMBERLY/post/Filtered-indexes-and-filtered-stats-might-become-seriously-out-of-date.aspx&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blogs.technet.com/josebda/archive/2009/03/17/indexing-best-practices-for-sql-server-2008.aspx"&gt;http://blogs.technet.com/josebda/archive/2009/03/17/indexing-best-practices-for-sql-server-2008.aspx&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=429409" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Sql+Server/default.aspx">Sql Server</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category></item><item><title>CodeRush plugin "Navigate to Implementation" - binaries for CodeRush 9.2.4</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/08/30/coderush-plugin-quot-navigate-to-implementation-quot-binaries-for-coderush-9-2-4.aspx</link><pubDate>Sun, 30 Aug 2009 17:56:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:390806</guid><dc:creator>Kim</dc:creator><slash:comments>16</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=390806</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/08/30/coderush-plugin-quot-navigate-to-implementation-quot-binaries-for-coderush-9-2-4.aspx#comments</comments><description>&lt;p&gt;For convenience, &lt;a href="http://blogs.microsoft.co.il/blogs/kim/Navigate2Impl%20CR%209.2.4.zip"&gt;here&lt;/a&gt; are the binaries for the Navigate to Implementation CodeRush&amp;nbsp;plugin.&amp;nbsp;It is&amp;nbsp;built against CodeRush 9.2.4. A detailed overview of the functionality of the plugin can be found &lt;a href="http://blogs.microsoft.co.il/blogs/kim/archive/2008/10/19/coderush-plugin-navigate-to-implementation-part-1.aspx"&gt;here&lt;/a&gt;. The source code is available on Google Code: &lt;a href="http://dxcorecommunityplugins.googlecode.com/svn/trunk/CR_NavigationContrib"&gt;http://dxcorecommunityplugins.googlecode.com/svn/trunk/CR_NavigationContrib&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=390806" width="1" height="1"&gt;</description><enclosure url="http://blogs.microsoft.co.il/blogs/kim/attachment/390806.ashx" length="10314" type="application/x-zip-compressed" /><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/CodeRush/default.aspx">CodeRush</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Plugin/default.aspx">Plugin</category></item><item><title>Importing Large Xml Files to SQL Server Using SqlBulkCopy</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/06/15/importing-large-xml-files-to-sql-server-using-sqlbulkcopy.aspx</link><pubDate>Mon, 15 Jun 2009 21:00:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:338092</guid><dc:creator>Kim</dc:creator><slash:comments>26</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=338092</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/06/15/importing-large-xml-files-to-sql-server-using-sqlbulkcopy.aspx#comments</comments><description>&lt;p&gt;Say you have a large Xml file that contains relatively tabular data that you want to import into SQL Server. There are several ways to go about this. Let’s look at a couple of options. &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Load the file into an XDocument. Extract elements from the DOM using Linq and then use ADO.Net to insert the data into the database. &lt;/li&gt;
&lt;li&gt;Load the data into a DataSet using ReadXml and save the data to the database &lt;/li&gt;
&lt;li&gt;Read through the data using an Xml reader and save each record to the database &lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;Options number 1 and 2 requires that we load the entire document into memory before processing. We will work under the assumption that the files we receive are too large to load into memory. That leaves with option number 3 which allows us to read the file in a fast forward only mode where we only hold a small portion of the file in memory. Once an item has been processed and the reader moves forward, the previously read data is unavailable to the reader. The main bottleneck now is how do we push the data in a really efficient way into the database. First of all let’s look at some sample data.&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;xml&lt;/span&gt;&lt;span style="COLOR:blue;"&gt; &lt;/span&gt;&lt;span style="COLOR:red;"&gt;version&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;1.0&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt; &lt;/span&gt;&lt;span style="COLOR:red;"&gt;encoding&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;utf-8&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;?&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;lab_results&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;result&lt;/span&gt;&lt;span style="COLOR:blue;"&gt; &lt;/span&gt;&lt;span style="COLOR:red;"&gt;type&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;A01&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt; &lt;/span&gt;&lt;span style="COLOR:red;"&gt;origin&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;xb102&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;name&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;aaa&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;name&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;description&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;sample description1&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;description&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;result&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;result&lt;/span&gt;&lt;span style="COLOR:blue;"&gt; &lt;/span&gt;&lt;span style="COLOR:red;"&gt;type&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;A02&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt; &lt;/span&gt;&lt;span style="COLOR:red;"&gt;origin&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;xb103&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;name&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;bbb&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;name&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;description&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;sample description2&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;description&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;result&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;lab_results&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The files we are about to process contain lab results. Each file will contain somewhere between 5-8 million result elements. Each result element will contain approximately 150 characters. 150 characters * 2 (Unicode) * 5 million = about 1.5GB per file. Obviously we can’t read that into memory all at once. Another detail is that the file contains type and origin codes which needs to be mapped to their appropriate values in the database.&lt;/p&gt;
&lt;p&gt;Here’s the sample table structure that will have to hold the data we import.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/labresults_27D77EF5.jpg"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="lab results" border="0" alt="lab results" src="http://blogs.microsoft.co.il/blogs/kim/labresults_thumb_5AFE712F.jpg" width="669" height="287" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;LabResultOrigin and LabResultType are standard lookup tables. Here’s some sample data so we can conceptualize the conversions we will need to make later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;LabResultType&lt;/strong&gt;&lt;/p&gt;
&lt;table cellspacing="0" cellpadding="2"&gt;

&lt;tr&gt;
&lt;td valign="top"&gt;TypeId&lt;/td&gt;
&lt;td valign="top"&gt;Description&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;1&lt;/td&gt;
&lt;td valign="top"&gt;A01&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;2&lt;/td&gt;
&lt;td valign="top"&gt;A02&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;3&lt;/td&gt;
&lt;td valign="top"&gt;B01&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;LabResultOrigin&lt;/strong&gt;&lt;/p&gt;
&lt;table cellspacing="0" cellpadding="2"&gt;

&lt;tr&gt;
&lt;td valign="top"&gt;OriginId&lt;/td&gt;
&lt;td valign="top"&gt;Description&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;1&lt;/td&gt;
&lt;td valign="top"&gt;xb102&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;2&lt;/td&gt;
&lt;td valign="top"&gt;xb103&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;3&lt;/td&gt;
&lt;td valign="top"&gt;xz101&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;For example, when we process the Xml file we will need to convert the from the textual result type of “A01” to 1.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Importing the data&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When importing using SqlBulkCopy there are two ways to feed it data. One is to use a DataTable which we discarded above because of the size of the files. Another option is to use a DataReader. The problem is that there is no class in .Net that reads xml and implements the IDataReader interface.&lt;/p&gt;
&lt;p&gt;That means we will have to roll our own. Looking at the IDataReader interface it seems we will have to implement a boatload of methods. Or do we? &lt;br /&gt;Here’s a neat little trick that was mentioned in the passing in a comment by “jezemine” in &lt;a href="http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=83181" target="_blank"&gt;this&lt;/a&gt; blog post. &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a class that implements IDataReader. &lt;/li&gt;
&lt;li&gt;Press Alt+Shift+F10 to implement the interface members (with a throw NotImplementedException) &lt;/li&gt;
&lt;li&gt;Pass your class to SqlBulkCopy. It will break on a NotImplementedException of course. &lt;/li&gt;
&lt;li&gt;Go ahead and implement the method it crashed on. &lt;/li&gt;
&lt;li&gt;Repeat steps #3 and #4 until all required methods have been implemented.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;Only 3 out of more than 20 methods in IDataReader are actually used by SqlBulkCopy. Not too bad.&lt;/p&gt;
&lt;p&gt;We will create an XmlDataReader class that implements IDataReader so that we can pass it to SqlBulkCopy. The calling code will look something like the following:&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;XmlTextReader&lt;/span&gt; xmlTextReader = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;XmlTextReader&lt;/span&gt;(message.FileName))&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;SqlBulkCopy&lt;/span&gt; sqlBulkCopy = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;SqlBulkCopy&lt;/span&gt;(connectionString, &lt;span style="COLOR:#2b91af;"&gt;SqlBulkCopyOptions&lt;/span&gt;.TableLock))&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetupBulkCopy(sqlBulkCopy);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;var&lt;/span&gt; reader = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;LabResultDataReader&lt;/span&gt;(xmlTextReader);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlBulkCopy.WriteToServer(reader);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, there is no mention of an XmlDataReader, but rather a LabResultDataReader. I decided to split the reader into two distinct pieces. One is a general purpose XmlDataReader that can be used for other xml structures and not only the one in the sample. A special purpose LabResultDataReader is derived from XmlDataReader and this class knows how to handle the structure of the lab result xml file.&lt;/p&gt;
&lt;p&gt;In order to tell SqlBulkCopy how to map between the data in the file and the columns in the database we need some plumbing as seen in the call to SetupBulkCopy().&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;void&lt;/span&gt; SetupBulkCopy(&lt;span style="COLOR:#2b91af;"&gt;SqlBulkCopy&lt;/span&gt; sqlBulkCopy)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlBulkCopy.ColumnMappings.Add(&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;SqlBulkCopyColumnMapping&lt;/span&gt;(0, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;TypeId&amp;quot;&lt;/span&gt;));&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlBulkCopy.ColumnMappings.Add(&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;SqlBulkCopyColumnMapping&lt;/span&gt;(1, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;OriginId&amp;quot;&lt;/span&gt;));&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlBulkCopy.ColumnMappings.Add(&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;SqlBulkCopyColumnMapping&lt;/span&gt;(2, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;ResultName&amp;quot;&lt;/span&gt;));&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlBulkCopy.ColumnMappings.Add(&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;SqlBulkCopyColumnMapping&lt;/span&gt;(3, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;Description&amp;quot;&lt;/span&gt;));&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sqlBulkCopy.DestinationTableName = &lt;span style="COLOR:#a31515;"&gt;&amp;quot;LabResult&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that we didn’t include the LabResultId column in the mapping above. The reason for this is that the LabResultId is an Identity column and is generated automatically by SQL Server.&lt;/p&gt;
&lt;p&gt;The general purpose XmlDataReader is as follows:&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;abstract&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;XmlDataReader&lt;/span&gt; : &lt;span style="COLOR:#2b91af;"&gt;IDataReader&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;readonly&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; m_rowElementName;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;readonly&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;XmlReader&lt;/span&gt; m_xmlReader;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;readonly&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; m_fieldCount = -1;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;bool&lt;/span&gt; m_disposed;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;protected&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;IEnumerator&lt;/span&gt;&amp;lt;&lt;span style="COLOR:#2b91af;"&gt;XElement&lt;/span&gt;&amp;gt; m_enumerator;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;abstract&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;object&lt;/span&gt; GetValue(&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; i);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Initialize the XmlDataStreamer. After initialization call Read() to move the reader forward.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;xmlReader&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;XmlReader used to iterate the data. Will be disposed by when done.&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;fieldCount&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;IDataReader FiledCount.&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;rowElementName&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;Name of the XML element that contains row data&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; XmlDataReader(&lt;span style="COLOR:#2b91af;"&gt;XmlReader&lt;/span&gt; xmlReader, &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; fieldCount, &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; rowElementName)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_rowElementName = rowElementName;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_fieldCount = fieldCount;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_xmlReader = xmlReader;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_enumerator = GetXmlStream().GetEnumerator();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;bool&lt;/span&gt; Read()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; m_enumerator.MoveNext();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; FieldCount&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;get&lt;/span&gt; { &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; m_fieldCount; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;XElement&lt;/span&gt; CurrentElement&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;get&lt;/span&gt; { &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; m_enumerator.Current; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; http://msdn.microsoft.com/en-us/library/system.xml.linq.xstreamingelement.aspx&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;m_xmlReader&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;IEnumerable&lt;/span&gt;&amp;lt;&lt;span style="COLOR:#2b91af;"&gt;XElement&lt;/span&gt;&amp;gt; GetXmlStream()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;XElement&lt;/span&gt; rowElement;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (m_xmlReader)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_xmlReader.MoveToContent();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;while&lt;/span&gt; (m_xmlReader.Read())&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (IsRowElement())&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rowElement = &lt;span style="COLOR:#2b91af;"&gt;XElement&lt;/span&gt;.ReadFrom(m_xmlReader) &lt;span style="COLOR:blue;"&gt;as&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;XElement&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (rowElement != &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;yield&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; rowElement;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;bool&lt;/span&gt; IsRowElement()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (m_xmlReader.NodeType != &lt;span style="COLOR:#2b91af;"&gt;XmlNodeType&lt;/span&gt;.Element)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; m_xmlReader.Name == m_rowElementName;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;protected&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;virtual&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;void&lt;/span&gt; Dispose()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (m_disposed)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_enumerator.Dispose();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_disposed = &lt;span style="COLOR:blue;"&gt;true&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #region&lt;/span&gt; Members not required by SqlBulkCopy&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #region&lt;/span&gt; IDataReader Members&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;bool&lt;/span&gt; NextResult()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;NotImplementedException&lt;/span&gt;();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; RecordsAffected&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;get&lt;/span&gt; { &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;NotImplementedException&lt;/span&gt;(); }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; GetDataTypeName(&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; i)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;NotImplementedException&lt;/span&gt;();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:green;"&gt;    // Deleted tons of methods not required...&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let’s have a look at the special purpose LabResult reader.&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;LabResultDataReader&lt;/span&gt; : &lt;span style="COLOR:#2b91af;"&gt;XmlDataReader&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;const&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; XmlTagRow = &lt;span style="COLOR:#a31515;"&gt;&amp;quot;result&amp;quot;&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;const&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; FieldCount = 4;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;const&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; InvalidItemId = -1;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; LabResultDataReader(&lt;span style="COLOR:#2b91af;"&gt;XmlReader&lt;/span&gt; xmlReader)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : &lt;span style="COLOR:blue;"&gt;base&lt;/span&gt;(xmlReader, FieldCount, XmlTagRow){ }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;override&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;object&lt;/span&gt; GetValue(&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; i)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;switch&lt;/span&gt; (i)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;case&lt;/span&gt; 0:&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; CurrentElement.Attribute(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;).EnumFromValue&amp;lt;&lt;span style="COLOR:#2b91af;"&gt;ResultType&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;case&lt;/span&gt; 1:&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; CurrentElement.Attribute(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;origin&amp;quot;&lt;/span&gt;).EnumFromValue&amp;lt;&lt;span style="COLOR:#2b91af;"&gt;Origin&lt;/span&gt;&amp;gt;();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;case&lt;/span&gt; 2:&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; CurrentElement.Element(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;).value;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;case&lt;/span&gt; 3:&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; CurrentElement.Element(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;description&amp;quot;&lt;/span&gt;).value;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;default&lt;/span&gt;:&lt;/pre&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;                throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;Column count mismatch.&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are two main features of the XmlDataReader. The first is that it flattens the Xml hierarchical structure to resemble a row. For each iteration of the enumerator, it extracts the &amp;lt;result&amp;gt; element and all its children. The special purpose reader (in our example the LabResultsDataReader) maps the nested &amp;lt;result&amp;gt; tag to a set of column values. The second significant feature is the streaming nature of the reader. We never hold more than a single &amp;lt;result&amp;gt; element in memory at any given time.&lt;/p&gt;
&lt;p&gt;If you look at the code above and wondered what are those .EnumFromValue&amp;lt;&amp;gt; methods on the XmlAttributes, you were right. These are just Extension methods that I added for convenience.&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; T EnumFromValue&amp;lt;T&amp;gt;(&lt;span style="COLOR:blue;"&gt;this&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;XAttribute&lt;/span&gt; attribute)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; value = attribute.Value;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;.IsNullOrEmpty(value))&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;default&lt;/span&gt;(T);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;try&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T converted = (T)&lt;span style="COLOR:#2b91af;"&gt;Enum&lt;/span&gt;.Parse(&lt;span style="COLOR:blue;"&gt;typeof&lt;/span&gt;(T), value, &lt;span style="COLOR:blue;"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; converted;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;catch&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;Exception&lt;/span&gt;)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;default&lt;/span&gt;(T);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, despite that this turned into a not so short post, there’s not that much code required for this to work. Hopefully this will give you enough to assist you in building your own high performance ETL solution.&lt;/p&gt;
&lt;p&gt;A few drawbacks of the proposed solution. I have only had to process a very limited set of files. In the case where many files of different schema would have to be parsed and processed, the design of having a designated derived class for each type of file could become a pain point. There is no support for parsing files with a schema that is not known at compile time. This implies that if the schema changes or a new type of file needs to be imported, a new build is needed.&lt;/p&gt;
&lt;p&gt;Suggestions, comments, improvements etc. are welcome.&lt;/p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fkim%2farchive%2f2009%2f06%2f15%2fimporting-large-xml-files-to-sql-server-using-sqlbulkcopy.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fkim%2farchive%2f2009%2f06%2f15%2fimporting-large-xml-files-to-sql-server-using-sqlbulkcopy.aspx" /&gt;&lt;/a&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=338092" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Sql+Server/default.aspx">Sql Server</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/SqlBulkCopy/default.aspx">SqlBulkCopy</category></item><item><title>Multi-Threading is Hard – Who do you trust?</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/06/04/multi-threading-is-hard-who-do-you-trust.aspx</link><pubDate>Thu, 04 Jun 2009 15:22:54 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:329955</guid><dc:creator>Kim</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=329955</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/06/04/multi-threading-is-hard-who-do-you-trust.aspx#comments</comments><description>&lt;p&gt;Something has been bothering me for quite some time and I am frankly not entirely sure what to do.&lt;/p&gt;  &lt;p&gt;I have been working on a multi-threaded server application for over a year and feel that I have a decent grasp on multi-threading. More importantly, I have learned to respect the complexity.&lt;/p&gt;  &lt;p&gt;So what is bothering me? Over the last few months I have encountered a number of blog posts that propose some solution with code that multi-threaded. &lt;/p&gt;  &lt;p&gt;The problem – It’s Wrong!&lt;/p&gt;  &lt;p&gt;Sometimes I send an email to the author, but for the most part, the posts are not being updated. That leaves the potential for other developers to take code from their trusted source and use it. Only to find down the road, maybe only after a year in production when the volume strains the system. You might claim that you cannot trust anyone, but multi-threading is complex enough that it is easy to be tempted to grab something from someone you otherwise believe knows his stuff. The problem I see most often is that of a lack of understanding of memory barriers and volatility. This is a basic concept if you do any kind of multi-threading and I am mostly surprised.&lt;/p&gt;  &lt;p&gt;Besides sending an email to the author I am not going to start to blog about bad sources for multi-threading.&lt;/p&gt;  &lt;p&gt;So where do you go?&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;I enjoyed Joe Duffy’s book &lt;a href="http://www.amazon.com/Concurrent-Programming-Windows-Microsoft-Development/dp/032143482X/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1244101713&amp;amp;sr=1-1" target="_blank"&gt;Concurrent Programming on Windows&lt;/a&gt;.&lt;/li&gt;    &lt;li&gt;I remember reading the &lt;a href="http://www.albahari.com/threading/" target="_blank"&gt;following tutorial&lt;/a&gt; a long time ago and liked it. &lt;/li&gt;    &lt;li&gt;I have followed Sasha Goldstein’s blog for a long time and I have been to presentations given by him. His &lt;a href="http://blogs.microsoft.co.il/blogs/sasha/" target="_blank"&gt;blog&lt;/a&gt; is a good source.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Don’t trust code you find online. If you don’t understand it, don’t use it. (assuming it is not copyrighted and that you are allowed to grab it)&lt;/p&gt;  &lt;p&gt;Do you know of any good sources for multi-threaded programming? &lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=329955" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Blog/default.aspx">Blog</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Concurrency/default.aspx">Concurrency</category></item><item><title>A Must Read - Release It! </title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/05/30/a-must-read-release-it.aspx</link><pubDate>Sun, 31 May 2009 01:21:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:316002</guid><dc:creator>Kim</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=316002</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/05/30/a-must-read-release-it.aspx#comments</comments><description>&lt;p&gt;I just finished reading &lt;a href="http://www.amazon.com/Release-Production-Ready-Software-Pragmatic-Programmers/dp/0978739213/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1243707688&amp;amp;sr=1-1"&gt;Release It&lt;/a&gt;&amp;nbsp;by Michael Nygard. The book deals with the topic of having software in production. Over the years I&amp;#39;ve been on quite a few projects from the requirements phase through development and eventually production. (No, not all of them reached production) &lt;/p&gt;
&lt;p&gt;I can&amp;#39;t give enough compliments about the book. The writing style is a brilliant mix of development related issues and&amp;nbsp;&amp;quot;war&amp;quot; stories from Michael&amp;#39;s own experiences. It covers&amp;nbsp;both anti-patterns&amp;nbsp;and patterns required for successful survival in a production environment.&lt;/p&gt;
&lt;p&gt;From the editiorial review:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In &lt;i&gt;Release It!&lt;/i&gt;, Michael T. Nygard shows you how to design and&lt;br /&gt;architect your application for the harsh realities it will face.&lt;br /&gt;You&amp;#39;ll learn how to design your application for maximum uptime,&lt;br /&gt;performance, and return on investment.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Nitpickers corner:&amp;nbsp;The only&amp;nbsp;issue I&amp;nbsp;found less than optimal was the placement of the sidebars. The sidebars are sometimes located such that I either&amp;nbsp;had to interupt my reading flow to read them, or go back a page later.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=316002" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Books/default.aspx">Books</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category></item><item><title>SqlBulkCopy Bug Workaround</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/05/20/sqlbulkcopy-bug-workaround.aspx</link><pubDate>Wed, 20 May 2009 15:11:09 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:299737</guid><dc:creator>Kim</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=299737</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/05/20/sqlbulkcopy-bug-workaround.aspx#comments</comments><description>&lt;p&gt;We are using SqlBulkCopy to import large xml documents into a database. However, we encountered a “minor” bug in the .Net Framework related to table naming. It turns out that if you have a dot “.” in the table name, SqlBulkCopy doesn’t work. The problem has been reported and a &lt;a href="http://support.microsoft.com/kb/944389" target="_blank"&gt;KB article is available&lt;/a&gt;, but without a workaround besides renaming the table. Our problem wasn’t with the actual name of the table(s), but with the name of the schema. The schema naming convention used in that specific database is [CompanyName.Project].TableName.&lt;/p&gt;  &lt;p&gt;The following code failes with the exception below. (Note the assignment to DestinationTable below.)&lt;/p&gt;  &lt;div style="font-size:10pt;background:white;color:black;font-family:consolas;"&gt;   &lt;pre style="margin:0px;"&gt;&lt;span style="color:#2b91af;"&gt;IDataReader&lt;/span&gt; reader = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;XmlDataStreamer&lt;/span&gt;(&lt;span style="color:green;"&gt;/* other stuff here */&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;SqlBulkCopy&lt;/span&gt; sqlBulkCopy = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SqlBulkCopy&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;Server=(local);Database=ScratchDb;Trusted_Connection=True;&amp;quot;&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;SqlBulkCopyOptions&lt;/span&gt;.TableLock))&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;{&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; sqlBulkCopy.DestinationTableName = &lt;span style="color:#a31515;"&gt;&amp;quot;[SchemaPart1.Part2].ImportTable&amp;quot;&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; sqlBulkCopy.WriteToServer(reader);&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/SqlBulkException_726F0E59.jpg"&gt;&lt;img title="SqlBulkException" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="323" alt="SqlBulkException" src="http://blogs.microsoft.co.il/blogs/kim/SqlBulkException_thumb_356FFE29.jpg" width="508" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;For the sake of argument, let’s just say that it is beyond our control to change the naming of the schema. After Googling around for a solution, it appeared to be more than a few with the same problem. Now what do we do? &lt;/p&gt;

&lt;p&gt;My first thought was to try to figure out if there’s a way to manipulate .Net into accepting the table name. After spending some quality time with Reflector it was time to take a walk and think about something else. I discussed the issue with one of the other developers on the team. While describing the issue a solution took form. &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;If I can’t change the .Net Framework and I can’t change the schema/table name, maybe I can somehow disguise the table name. Being inspired by dynamic languages lately - If it looks like a table and behaves like a table it must be a table. (Not really, but maybe .Net won’t notice the difference)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Solution: &lt;strong&gt;Use a view!&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;In the database create a new schema without dots in the name. &lt;/li&gt;

  &lt;li&gt;Create a view over the import table with a one-to-one mapping to the table. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That leaves us with a view named: [CompanyNameProjectImport].ImportTableView&lt;/p&gt;

&lt;p&gt;The following works:&lt;/p&gt;

&lt;div style="font-size:10pt;background:white;color:black;font-family:consolas;"&gt;
  &lt;pre style="margin:0px;"&gt;&lt;span style="color:#2b91af;"&gt;IDataReader&lt;/span&gt; reader = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;XmlDataStreamer&lt;/span&gt;(&lt;span style="color:green;"&gt;/* other stuff here */&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; (&lt;span style="color:#2b91af;"&gt;SqlBulkCopy&lt;/span&gt; sqlBulkCopy = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;SqlBulkCopy&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;Server=(local);Database=ScratchDb;Trusted_Connection=True;&amp;quot;&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;SqlBulkCopyOptions&lt;/span&gt;.TableLock))&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;{&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; sqlBulkCopy.DestinationTableName = &lt;span style="color:#a31515;"&gt;&amp;quot;[CompanyNameProjectImport].ImportTableView&amp;quot;&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;#160;&amp;#160;&amp;#160; sqlBulkCopy.WriteToServer(reader);&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;}&lt;/pre&gt;
&lt;/div&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=299737" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Data+Access/default.aspx">Data Access</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/SqlBulkCopy/default.aspx">SqlBulkCopy</category></item><item><title>How Many Rows in a Table?</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/04/30/how-many-rows-in-a-table.aspx</link><pubDate>Thu, 30 Apr 2009 22:06:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:279016</guid><dc:creator>Kim</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=279016</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/04/30/how-many-rows-in-a-table.aspx#comments</comments><description>&lt;p&gt;Have you ever wondered how many rows your SQL Server database tables contains?&lt;/p&gt;
&lt;p&gt;A few times now I&amp;#39;ve wanted to grab a list of table names with the row count for each table. In &lt;a href="http://www.sqlservercurry.com/2009/04/8-common-uses-of-undocumented-stored.html"&gt;a post&lt;/a&gt; about a few undocumented Stored Procedures I came across this neat script.&lt;br /&gt;&lt;span style="COLOR:blue;"&gt;&lt;br /&gt;EXEC &lt;/span&gt;sp_MSforeachtable &lt;span style="COLOR:#a31515;"&gt;&amp;#39;SELECT &amp;#39;&amp;#39;?&amp;#39;&amp;#39;, Count(*) as NumberOfRows FROM ?&amp;#39;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It uses&amp;nbsp;an undocumented stored procedure that iterates over all user tables in the database. The only issue I had with it, was that the output was really&amp;nbsp;tedious to read. I wanted a simple tabular display showing me&amp;nbsp;a list of tables with their name and number of rows, but sorted in descending order by the number of rows. Note that you can get this information in Management Studio&lt;/p&gt;
&lt;p&gt;Here&amp;#39;s a short script that does that...&lt;/p&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:blue;FONT-SIZE:10pt;"&gt;if&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:gray;FONT-SIZE:10pt;"&gt;(&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:fuchsia;FONT-SIZE:10pt;"&gt;object_id&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:blue;FONT-SIZE:10pt;"&gt; &lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:gray;FONT-SIZE:10pt;"&gt;(&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:red;FONT-SIZE:10pt;"&gt;&amp;#39;tempdb.dbo.#TableRowCount&amp;#39;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:gray;FONT-SIZE:10pt;"&gt;)&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt; &lt;span style="COLOR:gray;"&gt;is&lt;/span&gt; &lt;span style="COLOR:gray;"&gt;not&lt;/span&gt; &lt;span style="COLOR:gray;"&gt;null)&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt;&lt;span style="COLOR:blue;"&gt;drop&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;table&lt;/span&gt; #TableRowCount&lt;br /&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:blue;FONT-SIZE:10pt;"&gt;go&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:blue;FONT-SIZE:10pt;"&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:blue;FONT-SIZE:10pt;"&gt;&lt;br /&gt;create&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt;&amp;nbsp;&lt;span style="COLOR:blue;"&gt;table&lt;/span&gt; #TableRowCount&amp;nbsp;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:blue;FONT-SIZE:10pt;"&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:gray;FONT-SIZE:10pt;"&gt;(&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt;Id&amp;nbsp;&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;identity&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;(&lt;/span&gt;1&lt;span style="COLOR:gray;"&gt;,&lt;/span&gt;1&lt;span style="COLOR:gray;"&gt;)&lt;/span&gt; &lt;span style="COLOR:gray;"&gt;NOT&lt;/span&gt; &lt;span style="COLOR:gray;"&gt;NULL&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:blue;"&gt;primary&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;key&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt;&lt;span style="COLOR:gray;"&gt;,&lt;/span&gt;TableName &lt;span style="COLOR:blue;"&gt;nvarchar&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;(&lt;/span&gt;100&lt;span style="COLOR:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;,&lt;/span&gt;RowsInTable &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:gray;FONT-SIZE:10pt;"&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:green;FONT-SIZE:10pt;"&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:blue;FONT-SIZE:10pt;"&gt;&lt;br /&gt;insert&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt;&amp;nbsp;&lt;span style="COLOR:blue;"&gt;into&lt;/span&gt; #TableRowCount&lt;span style="COLOR:blue;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;(&lt;/span&gt;TableName&lt;span style="COLOR:gray;"&gt;,&lt;/span&gt; RowsInTable&lt;span style="COLOR:gray;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp; exec&lt;/span&gt; &lt;span style="COLOR:maroon;"&gt;sp_MSforeachtable&lt;/span&gt;&lt;span style="COLOR:blue;"&gt; &lt;/span&gt;&lt;span style="COLOR:red;"&gt;&amp;#39;SELECT &amp;#39;&amp;#39;?&amp;#39;&amp;#39;, Count(*) as NumberOfRows FROM ?&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:red;FONT-SIZE:10pt;"&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:blue;FONT-SIZE:10pt;"&gt;select&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt; &lt;span style="COLOR:gray;"&gt;*&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;from&lt;/span&gt; #TableRowCount &lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;COLOR:blue;FONT-SIZE:10pt;"&gt;order&lt;/span&gt;&lt;span style="FONT-FAMILY:&amp;#39;Courier New&amp;#39;;FONT-SIZE:10pt;"&gt; &lt;span style="COLOR:blue;"&gt;by&lt;/span&gt; RowsInTable &lt;span style="COLOR:blue;"&gt;desc&lt;/span&gt;&lt;/span&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Alternatively you can use the following script (which is what Management Studio uses)&lt;br /&gt;&lt;font size="2"&gt;&lt;br /&gt;&lt;font color="#0000ff"&gt;select &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;[name] &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;AS&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; TableName&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;,&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt;TableRowCount &lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;=&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;(&lt;br /&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;select&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font color="#ff00ff" size="2"&gt;&lt;font color="#ff00ff" size="2"&gt;sum&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt; &lt;/font&gt;&lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;(&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt;spart&lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;.&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;rows&lt;/font&gt;&lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;)&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;from&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font color="#008000" size="2"&gt;&lt;font color="#008000" size="2"&gt;sys&lt;/font&gt;&lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;.&lt;/font&gt;&lt;/font&gt;&lt;font color="#008000" size="2"&gt;&lt;font color="#008000" size="2"&gt;partitions&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; spart&amp;nbsp;&lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;where&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; spart&lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;.&lt;/font&gt;&lt;/font&gt;&lt;font color="#ff00ff" size="2"&gt;&lt;font color="#ff00ff" size="2"&gt;object_id&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;=&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; tbl&lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;.&lt;/font&gt;&lt;/font&gt;&lt;font color="#ff00ff" size="2"&gt;&lt;font color="#ff00ff" size="2"&gt;object_id&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;and&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; spart&lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;.&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt;index_id &lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;&amp;lt;&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; 2 &lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;)&lt;br /&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;from&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font color="#008000" size="2"&gt;&lt;font color="#008000" size="2"&gt;sys&lt;/font&gt;&lt;/font&gt;&lt;font color="#808080" size="2"&gt;&lt;font color="#808080" size="2"&gt;.&lt;/font&gt;&lt;/font&gt;&lt;font color="#008000" size="2"&gt;&lt;font color="#008000" size="2"&gt;tables&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; tbl&lt;br /&gt;&lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;order&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;by&lt;/font&gt;&lt;/font&gt;&lt;font size="2"&gt; TableRowCount &lt;/font&gt;&lt;font color="#0000ff" size="2"&gt;&lt;font color="#0000ff" size="2"&gt;desc&lt;/p&gt;&lt;/font&gt;&lt;/font&gt;
&lt;p&gt;Which do you prefer?&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=279016" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Sql+Server/default.aspx">Sql Server</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category></item><item><title>Solving an Expensive Database Lookup</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/04/26/solving-an-expensive-database-lookup.aspx</link><pubDate>Mon, 27 Apr 2009 02:57:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:276288</guid><dc:creator>Kim</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=276288</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/04/26/solving-an-expensive-database-lookup.aspx#comments</comments><description>&lt;p&gt;We had an interesting problem the other day. In our database (SQL Server 2008) we have a few tables with possibly many millions of records. We send some of the data from these and related tables to a third party service for processing and get status reports back. The problem was that the reports that we get back cannot easily be correlated back to the original records in our database.&lt;/p&gt;
&lt;p&gt;Let’s say we have a person table and an address table with a 1:m relationship between person and address. &lt;br /&gt;The tables could look something like:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/Capture_0E9F1063.jpg"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;" title="Capture" border="0" alt="Capture" src="http://blogs.microsoft.co.il/blogs/kim/Capture_thumb_75414FEC.jpg" width="435" height="198" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Together with the person and address data we send some additional data points for processing. The processing report contains the following data.&lt;/p&gt;
&lt;p&gt;ProcessingResult, FirstName, LastName, AddressLine1, AddressLine2, City, State, Zip.&lt;/p&gt;
&lt;p&gt;When we receive the processing report we need to correlate between the person record&lt;strong&gt;(s)&lt;/strong&gt; and the processing result for that name and address. (Could you have two people with the same name at the same address?)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So what do you do if there are 10,000,000 person records with the same amount of addresses?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I don’t know what your first thought is, but my first thought was that either we index the data in some way or this won’t work. You can’t do a table-scan on 10 million rows. From there the next thought that came to mind was to index on all the address columns to limit the resultset down to the persons with a given address. Essentially a covering index on Address. Doable, but there has to be a better way. My issue with this approach is that this index is expensive both in terms of space and IO.&lt;/p&gt;
&lt;p&gt;Let’s rephrase the question: &lt;br /&gt;&lt;strong&gt;“How can we create an alternative representation of Address that allows us to limit the number of matches?”&lt;/strong&gt; &lt;br /&gt;It doesn’t have to be exact. If the result would return, say 100 addresses, we could just do an exhaustive search on those and compare all columns with the data returned from the service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Spoiler below…&lt;/strong&gt;&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; Hash(&lt;span style="COLOR:#2b91af;"&gt;Address&lt;/span&gt; address)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;StringBuilder&lt;/span&gt; sb = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;StringBuilder&lt;/span&gt;(150);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sb.Append(address.AddressLine1);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sb.Append(address.AddressLine2);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sb.Append(address.City);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sb.Append(address.Zip);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; sb.Append(address.State);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Hasher&lt;/span&gt;(&lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt;.MD5).Hash(sb.ToString().ToLowerInvariant());&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Create a condensed representation of Address and store that representation with an index.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By hashing the address object using MD5, we obtain a 32 character string representation of the address. To store this hashed representation we can add a column to the address table named AddressHash and create an index on that column. Now, when we receive the processing report, we hash the address in the report and do a lookup against the hash value stored in the database. We then take any matching records (possibly only one) and do a comparison between the found record and the address from the service. &lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Here’s the Hasher class.&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;enum&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MD5,&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sha1,&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sha256,&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sha384,&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sha512,&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Hasher&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;HashAlgorithm&lt;/span&gt; m_hasher;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;readonly&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt; DefaultHashType = &lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt;.MD5;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Instantiates Hasher with the default HashType&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; Hasher()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_hasher = GetHasher(DefaultHashType);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; Hasher(&lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt; hashType)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_hasher = GetHasher(hashType);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Hash input and return the hashed result in a Hex string.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;input&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;Hash of input or null if input is null&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; Hash(&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; input)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;String&lt;/span&gt;.IsNullOrEmpty(input))&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;.Empty;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;byte&lt;/span&gt;[] data = m_hasher.ComputeHash(&lt;span style="COLOR:#2b91af;"&gt;Encoding&lt;/span&gt;.Unicode.GetBytes(input));&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; ToHex(data);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Verify that hasing input matches an existing hash value&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;input&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;The string to check against its hash&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;hash&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;returns&amp;gt;Match result or false if either parameter is null&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;bool&lt;/span&gt; IsHashMatch(&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; input, &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; hash)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;String&lt;/span&gt;.IsNullOrEmpty(input) || &lt;span style="COLOR:#2b91af;"&gt;String&lt;/span&gt;.IsNullOrEmpty(hash))&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;false&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; inputHash = Hash(input);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;.Compare(inputHash, hash, &lt;span style="COLOR:#2b91af;"&gt;StringComparison&lt;/span&gt;.OrdinalIgnoreCase) == 0;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; ToHex(&lt;span style="COLOR:blue;"&gt;byte&lt;/span&gt;[] data)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;StringBuilder&lt;/span&gt; builder = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;StringBuilder&lt;/span&gt;();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;for&lt;/span&gt; (&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; data.Length; i++)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; builder.Append(data[i].ToString(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;X&amp;quot;&lt;/span&gt;));&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; builder.ToString();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;HashAlgorithm&lt;/span&gt; GetHasher(&lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt; hashType)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;switch&lt;/span&gt; (hashType)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;case&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt;.MD5:&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;MD5&lt;/span&gt;.Create();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;case&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt;.Sha1:&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;SHA1&lt;/span&gt;.Create();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;case&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt;.Sha256:&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;SHA256&lt;/span&gt;.Create();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;case&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt;.Sha384:&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;SHA384&lt;/span&gt;.Create();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;case&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;HashType&lt;/span&gt;.Sha512:&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;SHA512&lt;/span&gt;.Create();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;default&lt;/span&gt;:&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentOutOfRangeException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;Unknown HashType&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;P.S While the Hex conversion of the hashed result is not an absolute requirement, we wanted to store the hash in a human readable format.&lt;/p&gt;
&lt;p&gt;How would you solve this problem to achieve better performance? (Storage is less important)&lt;/p&gt;
&lt;p&gt;Happy Coding!&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=276288" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/C_2300_/default.aspx">C#</category></item><item><title>Adapters and Functional Abstraction</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/02/23/adapters-and-functional-abstraction.aspx</link><pubDate>Tue, 24 Feb 2009 04:35:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:234704</guid><dc:creator>Kim</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=234704</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/02/23/adapters-and-functional-abstraction.aspx#comments</comments><description>&lt;p&gt;I can’t decide what I think about the following implementation so I decided to throw it out here. Any thoughts are welcome.&lt;/p&gt;
&lt;p&gt;In a &lt;a href="http://blogs.microsoft.co.il/blogs/kim/archive/2009/01/23/pgp-zip-encrypted-files-with-c.aspx"&gt;previous post&lt;/a&gt; I wrote about our wrapper around Bouncy Castle PGP encryption. Turned out it worked pretty well except one little problem. The PGP implementation on the receiving end would complain about our signature. In despair I even &lt;a class="" href="http://stackoverflow.com/questions/517635/pgp-encryption-with-bouncycastle-c-causes-invalid-key-warning-on-signature-verif"&gt;posted (and later answered) a question&lt;/a&gt; on StackOverflow. :-)&lt;/p&gt;
&lt;p&gt;The problem was that they use an old version of a PGP library that couldn’t deal with our newer v4 signatures. Oh, forget it, I’m not going to bore you with the details…&lt;/p&gt;
&lt;p&gt;I looked at the code for creating the object that does the signing and it returns an instance of a PgpSignatureGenerator (A Bouncy Castle class). Instead of using this signature generator we needed to use a PgpV3SignatureGenerator (Also a Bouncy Castle class). It was no big deal to change the code to instantiate and return a different type. However, we wanted to be able to return the v4 signature generator as well. Since both PgpSignatureGenerator and PgpV3SignatureGenerator are concrete implementations without a common base class we could not just return a common abstraction. Ok, still not a big deal. We can just create a wrapper (adapter) around the implementations and return that. &lt;br /&gt;&lt;br /&gt;That’s when you’re hit by the principle/rule police. SOLID, good? SOLID bad? should you prefer composition over inheritance or use a inheritance based version of the adapter pattern. Oh no, is this Adapter or is it Facade? … Just kidding… &lt;br /&gt;But I couldn’t resist it after the last couple of weeks of noise around principles and rules and whether they’re good or not.&lt;/p&gt;
&lt;p&gt;After a closer look at the two classes, I saw that they conform to the same interface (for the parts relevant to us at least). So I decided to skip over any design pattern I knew of and just take the shortest path to a solution that works. We need to make two calls on the signature generator while encrypting. This is after the initial setup of the signature generator. You can see the two signatures below. For this discussion it doesn’t matter what they accomplish.&lt;/p&gt;
&lt;div style="FONT-SIZE:10pt;BACKGROUND:white;COLOR:black;FONT-FAMILY:consolas;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;void&lt;/span&gt; Update(&lt;span style="COLOR:blue;"&gt;byte&lt;/span&gt;[] buffer, &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; offset, &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; length);&lt;br /&gt;&lt;/pre&gt;
&lt;div style="FONT-SIZE:10pt;BACKGROUND:white;COLOR:black;FONT-FAMILY:consolas;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpSignature&lt;/span&gt; Generate();&lt;/pre&gt;&lt;/div&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The following class captures this functionality and the caller doesn’t know at the time of calling the methods whether it’s a v4 or v3 signature.&lt;/p&gt;
&lt;div style="FONT-SIZE:10pt;BACKGROUND:white;COLOR:black;FONT-FAMILY:consolas;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Signer&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Action&lt;/span&gt;&amp;lt;&lt;span style="COLOR:blue;"&gt;byte&lt;/span&gt;[], &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt;, &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt;&amp;gt; Update { &lt;span style="COLOR:blue;"&gt;get&lt;/span&gt;; &lt;span style="COLOR:blue;"&gt;set&lt;/span&gt;; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="COLOR:#2b91af;"&gt;PgpSignature&lt;/span&gt;&amp;gt; Generate { &lt;span style="COLOR:blue;"&gt;get&lt;/span&gt;; &lt;span style="COLOR:blue;"&gt;set&lt;/span&gt;; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Signer can now be instantiated with either a v3 or v4 signature generator.&lt;/p&gt;
&lt;div style="FONT-SIZE:10pt;BACKGROUND:white;COLOR:black;FONT-FAMILY:consolas;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Signer&lt;/span&gt; GetSignatureGenerator(&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; compressedOut, &lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;SignatureVersion&lt;/span&gt; signatureVersion)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (signatureVersion == &lt;span style="COLOR:#2b91af;"&gt;SignatureVersion&lt;/span&gt;.V3)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpV3SignatureGenerator&lt;/span&gt; pgpV3SignatureGenerator = &lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpV3SignatureGenerator&lt;/span&gt;(...);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:green;"&gt;// some more initialization code&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Signer&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Update = (data, offset, length) =&amp;gt; pgpV3SignatureGenerator.Update(data, offset, length),&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Generate = () =&amp;gt; pgpV3SignatureGenerator.Generate()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;else&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (signatureVersion == &lt;span style="COLOR:#2b91af;"&gt;SignatureVersion&lt;/span&gt;.V4)&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpSignatureGenerator&lt;/span&gt; pgpSignatureGenerator = &lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpSignatureGenerator&lt;/span&gt;(...);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:green;"&gt;// some more initialization code&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pgpSignatureGenerator.GenerateOnePassVersion(&lt;span style="COLOR:blue;"&gt;false&lt;/span&gt;).Encode(compressedOut);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Signer&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Update = (data, offset, length) =&amp;gt; pgpSignatureGenerator.Update(data, offset, length),&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Generate = () =&amp;gt; pgpSignatureGenerator.Generate()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;else&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;Invalid signature version&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can get a v3 signature generator by using the following.&lt;/p&gt;
&lt;div style="FONT-SIZE:10pt;BACKGROUND:white;COLOR:black;FONT-FAMILY:consolas;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;var&lt;/span&gt; signer = GetSignatureGenerator(compressedOut, &lt;span style="COLOR:#2b91af;"&gt;SignatureVersion&lt;/span&gt;.V3);&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While it might not be entirely idiomatic to encapsulate by capturing only the behavior of the adaptee, I kind of like the minimalistic approach. It migth break in more complex scenarios&amp;nbsp;without a common interface, but for the simple stuff I think I like it.&lt;/p&gt;
&lt;p&gt;So what do you think? &lt;br /&gt;Nice? Ugly? other?&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=234704" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Programming+Style/default.aspx">Programming Style</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Design+Patterns/default.aspx">Design Patterns</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Encryption/default.aspx">Encryption</category></item><item><title>Visual Studio Color Scheme – Done for now</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/02/09/visual-studio-color-scheme-done-for-now.aspx</link><pubDate>Tue, 10 Feb 2009 04:33:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:225906</guid><dc:creator>Kim</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=225906</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/02/09/visual-studio-color-scheme-done-for-now.aspx#comments</comments><description>&lt;p&gt;After a tough last week where I spent far too much time debugging encryption keys, I needed something to relax. I haven’t tweaked my Visual Studio color settings in a while (a couple of years) so I spent a couple hours today refining them.&lt;/p&gt;
&lt;p&gt;You probably don’t want to know what I do when I’ve had a really bad week. Ok, I’ll let you know. I put on some music I like and watch Defrag. Preferably at 2 AM. I don’t know who’s idiotic idea it was to remove the graphical defrag interface from Windows, but I have Diskeeper which also does a better job of defragging.&lt;/p&gt;
&lt;p&gt;Where was I ? Oh, color settings. &lt;/p&gt;
&lt;p&gt;Here it is. Let me know what you think…&lt;/p&gt;
&lt;p&gt;&lt;img height="1" alt="" width="1" border="0" /&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/vscolor.JPG"&gt;&lt;img src="http://blogs.microsoft.co.il/blogs/kim/vscolor.JPG" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/vscolor_7AA244FE.jpg"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="" href="http://blogs.microsoft.co.il/blogs/kim/kim-dark1.zip"&gt;VS2008 Settings file&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=225906" width="1" height="1"&gt;</description><enclosure url="http://blogs.microsoft.co.il/blogs/kim/attachment/225906.ashx" length="66465" type="application/x-zip-compressed" /><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category></item><item><title>PGP Zip Encrypted Files With C#</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/01/23/pgp-zip-encrypted-files-with-c.aspx</link><pubDate>Fri, 23 Jan 2009 17:14:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:215806</guid><dc:creator>Kim</dc:creator><slash:comments>75</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=215806</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/01/23/pgp-zip-encrypted-files-with-c.aspx#comments</comments><description>&lt;p&gt;On a recent project here at &lt;a href="http://www.renaissance.co.il/"&gt;Renaissance&lt;/a&gt;, we needed to send files over FTP to some third party vendor. One of the requirements was that the files had to be encrypted using PGP (Pretty Good Privacy). After some research we decided to use &lt;a href="http://www.bouncycastle.org/"&gt;Bouncy Castle&lt;/a&gt;. Bouncy Castle is an open source C# implementation of the OpenPGP standard. It is available in Java as well. &lt;br /&gt;An additional requirement was that the PGP Encrypted files needed to be signed as well. &lt;/p&gt;
&lt;p&gt;If you have no background in cryptology or PGP and this sounds like gibberish, here’s a short simplified background on symmetric key encryption. &lt;/p&gt;
&lt;p&gt;To share PGP encrypted files the sender and recipient both need two keys. One public and one private. The sender encrypts the file to send with the recipients public key and sign with his private key. Both parties then exchange public keys. Each party can decrypt using its own private key and it can verify who sent the file using the senders public key.&lt;/p&gt;
&lt;p&gt;If this still sounds gibberish, I found this illustration on the &lt;a href="http://linomasoftware.com/"&gt;LinomaSoftware&lt;/a&gt; site a good visual explanation. (never used it, just searched Google for PGP image)&lt;/p&gt;
&lt;p&gt;&lt;img src="http://linomasoftware.com/images/graphics/sign&amp;amp;encrpt.jpg" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;With that out of the way, how hard can it be to encrypt and sign a file? Not very hard, but far too much code to write. We found a few samples online, but nothing I felt comfortable to use in our codebase. Credits to &lt;a href="http://jopinblog.wordpress.com/2008/06/23/pgp-single-pass-sign-and-encrypt-with-bouncy-castle/"&gt;John Opincar&lt;/a&gt; who published a post on single pass encryption and signing. We used the blog post of his, the Bouncy test suites and a some trial and failure to get it working.&lt;/p&gt;
&lt;p&gt;One of the issues with all the sample code out there, is that there are so many responsibilities squeezed together that unless you know what the code is doing beforehand, it is hard to grasp. It was to me at least. That might be partially related to me having no significant background in cryptology or PGP.&lt;/p&gt;
&lt;p&gt;Lets see some code. No matter if I’m doing TDD or not, I always try to write the client code before the API. That way I shape the API from the point of view of the consuming code and avoid surprising and clunky interfaces later. I wanted the calling code to look like this.&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:9pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;void&lt;/span&gt; EncryptAndSign()&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;{&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpEncryptionKeys&lt;/span&gt; encryptionKeys = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpEncryptionKeys&lt;/span&gt;(&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PublicKeyFileName, PrivateKeyFileName, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;PasswordOfMyPrivateKey&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpEncrypt&lt;/span&gt; encrypter = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpEncrypt&lt;/span&gt;(encryptionKeys); &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; outputStream = &lt;span style="COLOR:#2b91af;"&gt;File&lt;/span&gt;.Create(EncryptedFileName))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; encrypter.EncryptAndSign(outputStream, &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;FileInfo&lt;/span&gt;(FileToEncrypt));&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;From the sample code above you can see that we have separated Key management code from the actual encryption code. The &lt;span style="COLOR:#2b91af;"&gt;PgpEncryptionKeys&lt;/span&gt; class instantiates and deals with the intricacies of key management. The &lt;span style="COLOR:#2b91af;"&gt;PgpEncrypt&lt;/span&gt; class does this actual encryption. There were two reasons for this separation. The first is that key management is a separate concern conceptually. Another is that while we currently point to the location of the key files, we might want to change that in the future. I want to be able to change the way we instantiate the keys without touching the encryption code. No efforts were made at this point to create interfaces and/or abstract classes for evolution or extensibility. We’ll do that when/if we’ll need it.&lt;/p&gt;
&lt;p&gt;Next we will have a look at the actual implementation. I will not walk through and explain all the code. We tried to make the code as self explanatory as possible. However, if you have no other background related to encryption and PGP besides this blog post, you should probably spend a few hours reading up on that before considering using this code. Treat this code As-Is with no commitment on my side to keep it up-to-date with bug fixes and improvements.&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:9pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; System;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; System.IO;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; System.Linq;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; Org.BouncyCastle.Bcpg.OpenPgp;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;namespace&lt;/span&gt; Renaissance.Common.Encryption&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;{&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpEncryptionKeys&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpPublicKey&lt;/span&gt; PublicKey { &lt;span style="COLOR:blue;"&gt;get&lt;/span&gt;; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpPrivateKey&lt;/span&gt; PrivateKey { &lt;span style="COLOR:blue;"&gt;get&lt;/span&gt;; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpSecretKey&lt;/span&gt; SecretKey { &lt;span style="COLOR:blue;"&gt;get&lt;/span&gt;; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;set&lt;/span&gt;; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Initializes a new instance of the EncryptionKeys class.&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Two keys are required to encrypt and sign data. Your private key and the recipients public key.&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; The data is encrypted with the recipients public key and signed with your private key.&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;publicKeyPath&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;The key used to encrypt the data&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;privateKeyPath&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;The key used to sign the data.&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;passPhrase&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;The (your) password required to access the private key&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;exception cref=&amp;quot;ArgumentException&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;Public key not found. Private key not found. Missing password&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/exception&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; PgpEncryptionKeys(&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; publicKeyPath, &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; privateKeyPath, &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; passPhrase)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (!&lt;span style="COLOR:#2b91af;"&gt;File&lt;/span&gt;.Exists(publicKeyPath))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;Public key file not found&amp;quot;&lt;/span&gt;, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;publicKeyPath&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (!&lt;span style="COLOR:#2b91af;"&gt;File&lt;/span&gt;.Exists(privateKeyPath))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;Private key file not found&amp;quot;&lt;/span&gt;, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;privateKeyPath&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;String&lt;/span&gt;.IsNullOrEmpty(passPhrase))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;passPhrase is null or empty.&amp;quot;&lt;/span&gt;, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;passPhrase&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PublicKey = ReadPublicKey(publicKeyPath);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SecretKey = ReadSecretKey(privateKeyPath);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PrivateKey = ReadPrivateKey(passPhrase);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #region&lt;/span&gt; Secret Key&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpSecretKey&lt;/span&gt; ReadSecretKey(&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; privateKeyPath)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; keyIn = &lt;span style="COLOR:#2b91af;"&gt;File&lt;/span&gt;.OpenRead(privateKeyPath))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; inputStream = &lt;span style="COLOR:#2b91af;"&gt;PgpUtilities&lt;/span&gt;.GetDecoderStream(keyIn))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpSecretKeyRingBundle&lt;/span&gt; secretKeyRingBundle = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpSecretKeyRingBundle&lt;/span&gt;(inputStream);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpSecretKey&lt;/span&gt; foundKey = GetFirstSecretKey(secretKeyRingBundle);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (foundKey != &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; foundKey;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;Can&amp;#39;t find signing key in key ring.&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Return the first key we can use to encrypt.&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Note: A file can contain multiple keys (stored in &amp;quot;key rings&amp;quot;) &lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpSecretKey&lt;/span&gt; GetFirstSecretKey(&lt;span style="COLOR:#2b91af;"&gt;PgpSecretKeyRingBundle&lt;/span&gt; secretKeyRingBundle)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;foreach&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;PgpSecretKeyRing&lt;/span&gt; kRing &lt;span style="COLOR:blue;"&gt;in&lt;/span&gt; secretKeyRingBundle.GetKeyRings())&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpSecretKey&lt;/span&gt; key = kRing.GetSecretKeys()&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Cast&amp;lt;&lt;span style="COLOR:#2b91af;"&gt;PgpSecretKey&lt;/span&gt;&amp;gt;()&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Where(k =&amp;gt; k.IsSigningKey)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .FirstOrDefault();&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (key != &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; key;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #endregion&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #region&lt;/span&gt; Public Key&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpPublicKey&lt;/span&gt; ReadPublicKey(&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; publicKeyPath)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; keyIn = &lt;span style="COLOR:#2b91af;"&gt;File&lt;/span&gt;.OpenRead(publicKeyPath))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; inputStream = &lt;span style="COLOR:#2b91af;"&gt;PgpUtilities&lt;/span&gt;.GetDecoderStream(keyIn))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpPublicKeyRingBundle&lt;/span&gt; publicKeyRingBundle = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpPublicKeyRingBundle&lt;/span&gt;(inputStream);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpPublicKey&lt;/span&gt; foundKey = GetFirstPublicKey(publicKeyRingBundle);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (foundKey != &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; foundKey;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;No encryption key found in public key ring.&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpPublicKey&lt;/span&gt; GetFirstPublicKey(&lt;span style="COLOR:#2b91af;"&gt;PgpPublicKeyRingBundle&lt;/span&gt; publicKeyRingBundle)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;foreach&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;PgpPublicKeyRing&lt;/span&gt; kRing &lt;span style="COLOR:blue;"&gt;in&lt;/span&gt; publicKeyRingBundle.GetKeyRings())&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpPublicKey&lt;/span&gt; key = kRing.GetPublicKeys()&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Cast&amp;lt;&lt;span style="COLOR:#2b91af;"&gt;PgpPublicKey&lt;/span&gt;&amp;gt;()&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Where(k =&amp;gt; k.IsEncryptionKey)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .FirstOrDefault();&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (key != &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; key;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #endregion&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #region&lt;/span&gt; Private Key&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpPrivateKey&lt;/span&gt; ReadPrivateKey(&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; passPhrase)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpPrivateKey&lt;/span&gt; privateKey = SecretKey.ExtractPrivateKey(passPhrase.ToCharArray());&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (privateKey != &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; privateKey;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;No private key found in secret key.&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #endregion&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;As you can see from the code and comments, PGP has a concept of key rings. In other words there can be many keys. We assume a single key.&lt;/p&gt;
&lt;p&gt;Now to the PGP encryption class&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:9pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; System;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; System.IO;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; Org.BouncyCastle.Bcpg;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; Org.BouncyCastle.Bcpg.OpenPgp;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; Org.BouncyCastle.Security;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;namespace&lt;/span&gt; Renaissance.Common.Encryption&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;{&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Wrapper around Bouncy Castle OpenPGP library.&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Bouncy documentation can be found here: http://www.bouncycastle.org/docs/pgdocs1.6/index.html&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpEncrypt&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpEncryptionKeys&lt;/span&gt; m_encryptionKeys;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;const&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; BufferSize = 0x10000; &lt;span style="COLOR:green;"&gt;// should always be power of 2&amp;nbsp; &lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Instantiate a new PgpEncrypt class with initialized PgpEncryptionKeys.&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;encryptionKeys&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;exception cref=&amp;quot;ArgumentNullException&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;encryptionKeys is null&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/exception&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; PgpEncrypt(&lt;span style="COLOR:#2b91af;"&gt;PgpEncryptionKeys&lt;/span&gt; encryptionKeys)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (encryptionKeys == &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentNullException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;encryptionKeys&amp;quot;&lt;/span&gt;, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;encryptionKeys is null.&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_encryptionKeys = encryptionKeys;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; Encrypt and sign the file pointed to by unencryptedFileInfo and &lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; write the encrypted content to outputStream.&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;outputStream&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;The stream that will contain the &lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; encrypted data when this method returns.&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:gray;"&gt;///&lt;/span&gt;&lt;span style="COLOR:green;"&gt; &lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;param name=&amp;quot;fileName&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style="COLOR:green;"&gt;FileInfo of the file to encrypt&lt;/span&gt;&lt;span style="COLOR:gray;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;void&lt;/span&gt; EncryptAndSign(&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; outputStream, &lt;span style="COLOR:#2b91af;"&gt;FileInfo&lt;/span&gt; unencryptedFileInfo)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (outputStream == &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentNullException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;outputStream&amp;quot;&lt;/span&gt;, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;outputStream is null.&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (unencryptedFileInfo == &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentNullException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;unencryptedFileInfo&amp;quot;&lt;/span&gt;, &lt;span style="COLOR:#a31515;"&gt;&amp;quot;unencryptedFileInfo is null.&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (!&lt;span style="COLOR:#2b91af;"&gt;File&lt;/span&gt;.Exists(unencryptedFileInfo.FullName))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;throw&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;ArgumentException&lt;/span&gt;(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;File to encrypt not found.&amp;quot;&lt;/span&gt;);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; encryptedOut = ChainEncryptedOut(outputStream))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; compressedOut = ChainCompressedOut(encryptedOut))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpSignatureGenerator&lt;/span&gt; signatureGenerator = InitSignatureGenerator(compressedOut);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; literalOut = ChainLiteralOut(compressedOut, unencryptedFileInfo))&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; (&lt;span style="COLOR:#2b91af;"&gt;FileStream&lt;/span&gt; inputFile = unencryptedFileInfo.OpenRead())&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WriteOutputAndSign(compressedOut, literalOut, inputFile, signatureGenerator);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;void&lt;/span&gt; WriteOutputAndSign(&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; compressedOut, &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; literalOut, &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;FileStream&lt;/span&gt; inputFile, &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpSignatureGenerator&lt;/span&gt; signatureGenerator)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; length = 0;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;byte&lt;/span&gt;[] buf = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;byte&lt;/span&gt;[BufferSize];&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;while&lt;/span&gt; ((length = inputFile.Read(buf, 0, buf.Length)) &amp;gt; 0)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; literalOut.Write(buf, 0, length);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; signatureGenerator.Update(buf, 0, length);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; signatureGenerator.Generate().Encode(compressedOut);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; ChainEncryptedOut(&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; outputStream)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpEncryptedDataGenerator&lt;/span&gt; encryptedDataGenerator;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; encryptedDataGenerator = &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpEncryptedDataGenerator&lt;/span&gt;(&lt;span style="COLOR:#2b91af;"&gt;SymmetricKeyAlgorithmTag&lt;/span&gt;.TripleDes, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;SecureRandom&lt;/span&gt;());&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; encryptedDataGenerator.AddMethod(m_encryptionKeys.PublicKey);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; encryptedDataGenerator.Open(outputStream, &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;byte&lt;/span&gt;[BufferSize]);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; ChainCompressedOut(&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; encryptedOut)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpCompressedDataGenerator&lt;/span&gt; compressedDataGenerator = &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpCompressedDataGenerator&lt;/span&gt;(&lt;span style="COLOR:#2b91af;"&gt;CompressionAlgorithmTag&lt;/span&gt;.Zip);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; compressedDataGenerator.Open(encryptedOut);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; ChainLiteralOut(&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; compressedOut, &lt;span style="COLOR:#2b91af;"&gt;FileInfo&lt;/span&gt; file)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpLiteralDataGenerator&lt;/span&gt; pgpLiteralDataGenerator = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpLiteralDataGenerator&lt;/span&gt;();&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; pgpLiteralDataGenerator.Open(compressedOut, &lt;span style="COLOR:#2b91af;"&gt;PgpLiteralData&lt;/span&gt;.Binary, file);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;private&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpSignatureGenerator&lt;/span&gt; InitSignatureGenerator(&lt;span style="COLOR:#2b91af;"&gt;Stream&lt;/span&gt; compressedOut)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;const&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;bool&lt;/span&gt; IsCritical = &lt;span style="COLOR:blue;"&gt;false&lt;/span&gt;;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;const&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;bool&lt;/span&gt; IsNested = &lt;span style="COLOR:blue;"&gt;false&lt;/span&gt;;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PublicKeyAlgorithmTag&lt;/span&gt; tag = m_encryptionKeys.SecretKey.PublicKey.Algorithm;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpSignatureGenerator&lt;/span&gt; pgpSignatureGenerator = &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpSignatureGenerator&lt;/span&gt;(tag, &lt;span style="COLOR:#2b91af;"&gt;HashAlgorithmTag&lt;/span&gt;.Sha1);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pgpSignatureGenerator.InitSign(&lt;span style="COLOR:#2b91af;"&gt;PgpSignature&lt;/span&gt;.BinaryDocument, m_encryptionKeys.PrivateKey);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;foreach&lt;/span&gt; (&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; userId &lt;span style="COLOR:blue;"&gt;in&lt;/span&gt; m_encryptionKeys.SecretKey.PublicKey.GetUserIds())&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;PgpSignatureSubpacketGenerator&lt;/span&gt; subPacketGenerator = &lt;br /&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;PgpSignatureSubpacketGenerator&lt;/span&gt;();&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; subPacketGenerator.SetSignerUserId(IsCritical, userId);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pgpSignatureGenerator.SetHashedSubpackets(subPacketGenerator.Generate());&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:green;"&gt;// Just the first one!&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;break&lt;/span&gt;;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pgpSignatureGenerator.GenerateOnePassVersion(IsNested).Encode(compressedOut);&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; pgpSignatureGenerator;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;It should be clear from the code above, but one concept that helped understand the implementation of the Bouncy classes was that they basically just creates a pipeline of streams. We expressed these as XXX ChainXXX(innerStream){} where the ChainXXX methods take the stream to wrap and returns the wrapped stream. Encapsulating this concept into small ChainXXX classes made the resulting code much more readable IMHO.&lt;/p&gt;
&lt;p&gt;Comments, corrections and improvements are welcome as always…&lt;/p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fkim%2farchive%2f2009%2f01%2f23%2fpgp-zip-encrypted-files-with-c.aspx"&gt;&lt;img border="0" alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fkim%2farchive%2f2009%2f01%2f23%2fpgp-zip-encrypted-files-with-c.aspx" /&gt;&lt;/a&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=215806" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/.NET/default.aspx">.NET</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Encryption/default.aspx">Encryption</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/PGP/default.aspx">PGP</category></item><item><title>Building a Lean Development Machine</title><link>http://blogs.microsoft.co.il/blogs/kim/archive/2009/01/12/building-a-lean-development-machine.aspx</link><pubDate>Tue, 13 Jan 2009 03:37:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:210437</guid><dc:creator>Kim</dc:creator><slash:comments>55</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.microsoft.co.il/blogs/kim/rsscomments.aspx?PostID=210437</wfw:commentRss><comments>http://blogs.microsoft.co.il/blogs/kim/archive/2009/01/12/building-a-lean-development-machine.aspx#comments</comments><description>&lt;p&gt;The time to rebuild my development machine had arrived again. I’ve been running Vista 32 bit&amp;nbsp;for about a year. I was basically happy with Vista as a development machine, but something else had bothered me over the last couple of months. All the mundane crap that was clogging my system. For example, Skype, Trillian, ITunes, Hamachi, PDF readers, MS Office … The list goes on and on…&lt;/p&gt;
&lt;p&gt;I want a super lean installation of Windows 2008 Server x64, Visual Studio 2008, Sql Server 2008 x64, TortoiseSVN, VisualSVN, CodeRush and WinMerge.&lt;/p&gt;
&lt;p&gt;The choice of Windows 2008 Server is to match our production servers which are running Windows 2008 Server.&lt;/p&gt;
&lt;p&gt;So that’s what I did. I installed the very short list of software above. I used &lt;a class="" href="http://www.win2008workstation.com/wordpress/2008/07/17/windows-server-2008-workstation-converter/"&gt;windows-server-2008-workstation-converter&lt;/a&gt; to make the server more suitable as a workstation. Visual Studio is incredibly fast on the new installation. I have decent hardware, but it is still a notebook. (Some disagree with me that the Dell XPS 1730 is&amp;nbsp;a notebook, but I’ll leave that as a dispute on definition of a notebook :-) )&lt;/p&gt;
&lt;p&gt;&lt;img height="209" src="http://area.autodesk.com/index.php?ACT=44&amp;amp;fid=62&amp;amp;aid=877_VB9HZg6jXH7oRkDuXMXP" width="294" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;For a notebook the hardware specs are pretty good.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/blogs/kim/image_44F5D122.png"&gt;&lt;img title="image" style="BORDER-RIGHT:0px;BORDER-TOP:0px;DISPLAY:inline;BORDER-LEFT:0px;BORDER-BOTTOM:0px;" height="284" alt="image" src="http://blogs.microsoft.co.il/blogs/kim/image_thumb_50831AA7.png" width="402" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;In addition it has 2 X 200GB 7200rpm HDD running in a RAID0 configuration.&lt;/p&gt;
&lt;p&gt;What about all the other software packages? Everything else I installed in a virtual machine running Windows XP Pro.&amp;nbsp;XP running in a VM on Win2k8 x64 on this machine is so fast you don’t even notice it’s running in a virtual machine. Sweet!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fkim%2farchive%2f2009%2f01%2f12%2fbuilding-a-lean-development-machine.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblogs.microsoft.co.il%2fblogs%2fkim%2farchive%2f2009%2f01%2f12%2fbuilding-a-lean-development-machine.aspx" border="0" /&gt;&lt;/a&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=210437" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/laptop/default.aspx">laptop</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/kim/archive/tags/TECH/default.aspx">TECH</category></item></channel></rss>