<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8340788719090141711</id><updated>2012-01-11T15:31:50.546+01:00</updated><category term='C#'/><category term='LINQ'/><category term='Windows Vista'/><category term='SQL'/><category term='Hardware'/><category term='XML'/><category term='#smellycode'/><category term='Ruby on Rails'/><category term='Windows'/><category term='WPF'/><category term='Google'/><category term='Programming'/><category term='Entity Framework'/><title type='text'>Manfred's Blog</title><subtitle type='html'>Blog about computer, software and programming.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>56</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-4359248330180793968</id><published>2011-03-09T16:48:00.000+01:00</published><updated>2011-03-09T16:48:47.898+01:00</updated><title type='text'>New version of Team Viewer</title><content type='html'>&lt;div style="text-align: justify;"&gt;Since my first blog post about Team Viewer has become a sort of "support forum", which has reached 125 comments now, I decided to write about the new version.&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;As I already wrote on my first post Team Viewer is really great if you have to help kin and kith with all sorts of computer problems. It is much easier and takes less time to solve a problem if you can see it as if someone (who does not know much about computers) describes you what he/she sees. You could also use remote desktop through the MSN Messenger but I tried it out and I had problems to get it to work. Firewalls are the biggest problem for not experienced users.&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Team Viewer is very easy to use and has no problems with firewalls; that is what I like so much about it; and of course that it is FREE for personal use ;-). Also a computer noob can run it and tell you the ID and the password. Team Viewer is also very useful to maintain remote machines such as your home server.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The application has reached version 6 now and they say that they have improved many things such as performance, usability and much more. If you are interested in all the details have a look at &lt;a href="http://www.teamviewer.com/en/download/tv6.aspx"&gt;http://www.teamviewer.com/en/download/tv6.aspx&lt;/a&gt;. You can also use it to share files with someone over the internet but since I’m using &lt;a href="http://db.tt/NZ2XMdg"&gt;DropBox&lt;/a&gt; to store and share files I don’t use this feature very much.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;Since I am a proud owner of an Android Smartphone (&lt;a href="http://galaxys.samsungmobile.com/index_2.html?ver=high"&gt;Samsung Galaxy S&lt;/a&gt;) I was curious to try out also the Team Viewer application for Android. It is really amazing how good it works!! I tried it over Wifi, where the speed is quite good, and over my mobile phone network where it goes much slower but is still usable. This allows me to help kin and kith with their computer problems also on the go :-)&amp;nbsp;There exists also an iPhone and iPad app but I couldn’t try it out because I don’t have one.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.teamviewer.com/en/index.aspx"&gt;Link to Team Viewer&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-4359248330180793968?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/4359248330180793968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=4359248330180793968' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4359248330180793968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4359248330180793968'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2011/03/new-version-of-team-viewer.html' title='New version of Team Viewer'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-454630460325405319</id><published>2010-11-29T19:12:00.000+01:00</published><updated>2010-11-29T19:12:22.605+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='#smellycode'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Smelly code</title><content type='html'>&lt;b&gt;&lt;u&gt;Original, smelly code&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;public bool isLocked(string s)&lt;br /&gt;{&lt;br /&gt;    if (!File.Exists(s)) return false;&lt;br /&gt;    try { FileStream f = File.Open(s, FileMode.Open, FileAccess.ReadWrite); f.Close(); }&lt;br /&gt;    catch { return true; }&lt;br /&gt;    return false;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Objections and Comments&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;The code abve has in my eyes several problems:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Method name starts with lower case&lt;/li&gt;&lt;li&gt;The name of the input parameter is meaningless&lt;/li&gt;&lt;li&gt;Logical code blocks are not separated by a new line&lt;/li&gt;&lt;li&gt;You need some time to understand what this 4 lines of code do&lt;/li&gt;&lt;li&gt;Multiple instructions on the same line&lt;/li&gt;&lt;li&gt;The "return false;" statement should be inside the try block because it is logically associated to it&lt;/li&gt;&lt;li&gt;Missing Method documentation&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Proposed Refactoring&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Checks if a file is in use or not.&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;param name="filePath"&amp;gt;The path to the file that should be checked.&amp;lt;/param&amp;gt;&lt;br /&gt;/// &amp;lt;returns&amp;gt;True if the file is locked; false otherwise&amp;lt;/returns&amp;gt;&lt;br /&gt;public bool IsLocked(string filePath)&lt;br /&gt;{&lt;br /&gt;    if (!File.Exists(filePath))&lt;br /&gt;    {&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        FileStream fileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite);&lt;br /&gt;        fileStream.Close();&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;    catch&lt;br /&gt;    {&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-454630460325405319?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/454630460325405319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=454630460325405319' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/454630460325405319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/454630460325405319'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2010/11/smelly-code.html' title='Smelly code'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-386465276105116836</id><published>2010-07-19T18:02:00.001+02:00</published><updated>2010-07-19T18:02:20.207+02:00</updated><title type='text'>Strange undestroyable folders</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;p align='justify'&gt;A friend of mine had a very very strange problem. Suddenly on his external hard disk there appeared a bunch of very strangely named folders like "%/sl94..." and other symbols which windows was not able to display. They occupied 300GB and clearly my friend wanted to delete them; unfortunately windows was not able to delete them. It gave always an error like "Path not found" or "Invalid path symbols".&lt;br/&gt;I tried then to delete them with different data shredders but none of them was able to successfully delete them. &lt;br/&gt;I have then run also different virus and spy-ware scanners over them but none of them found something.&lt;br/&gt;I was stuck and at the end with my knowledge.&lt;/p&gt;&lt;p&gt;Then I found on the Internet the good old command line instruction:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;del &lt;em&gt;foldername&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;With that I was finally able to delete them all.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-386465276105116836?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/386465276105116836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=386465276105116836' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/386465276105116836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/386465276105116836'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2010/07/strange-undestroyable-folders.html' title='Strange undestroyable folders'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-3875110895455980034</id><published>2010-07-19T17:54:00.001+02:00</published><updated>2010-07-19T17:54:54.414+02:00</updated><title type='text'>Direct SQL vs. View vs. Stored Procedure</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;p align='justify'&gt;I was wondering for a very very long time what all these "battels" around direct sql, views and stored procedures are about. I read several articles on the Internet where people were claiming that nowadays there is almost no difference anymore between these three database "constructs". I saw many discussions and blogs where people tested the performance of these three with different results and that made me even more confused.&lt;/p&gt;&lt;p align='justify'&gt;So as I am curious and the fact that I need to know this as a software developer I decided to try this out by myself. At work I had the chance to test this against a very large amount of real data (I needed to optimize this query anyway); &lt;br/&gt;Sometimes the sample databases which are used for theses kinds of tests are either very small or very simple or even both which makes not really sense in my eyes.&lt;/p&gt;&lt;p align='justify'&gt;So the query consisted of joins of multiple tables with a case in the select statement. I run the query 300 times with every "construct" and then I took the average value for all three of them in order to reduce network and SQL Server workload "noise".&lt;/p&gt;&lt;p&gt;&lt;strong&gt;The result of my test (in Ticks):&lt;/strong&gt;&lt;/p&gt;&lt;table cellpadding='0' cellspacing='2' border='0'&gt;&lt;tr&gt;&lt;td&gt;&lt;p align='left'&gt;Direct SQL&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p align='left'&gt;23077&lt;/p&gt;&lt;p align='left'/&gt;&lt;p/&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p align='left'&gt;View&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p align='left'&gt;19363&lt;/p&gt;&lt;p align='left'/&gt;&lt;p/&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p align='left'&gt;Stored procedure&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p align='left'&gt;3438&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p/&gt;&lt;p align='justify'&gt;So what I found out for myself is that it really does matter what kind of "construct" you use to query your data; especially on a large amount of data.&lt;br/&gt;On large data you should also take into consideration that a big performance impact may also have where you set your indexes and which statistical data you let create by SQL Server.&lt;/p&gt;&lt;p&gt;If you made other experiences on this, please let me know and leave a comment...&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-3875110895455980034?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/3875110895455980034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=3875110895455980034' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3875110895455980034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3875110895455980034'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2010/07/direct-sql-vs-view-vs-stored-procedure.html' title='Direct SQL vs. View vs. Stored Procedure'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-7421858668941341967</id><published>2010-07-19T17:33:00.001+02:00</published><updated>2010-07-19T17:33:26.919+02:00</updated><title type='text'>Executing SQLQueries on ObjectContext</title><content type='html'>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;p&gt;Recently I worked with the entity framework (3.5) and at some point I had the need to execute a custom SQL command. Fortunately does the object context provide the underlying DBConnection and with that you can simply execute SQLCommands.&lt;/p&gt;&lt;p&gt;I read on the Internet that the new Version (4.0) has already integrated something similar.&lt;/p&gt;&lt;p&gt;This is an extension Method that I wrote which makes it easy to execute these queries:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;public static void ExecuteSQL(this ObjectContext context, string sql)&lt;br /&gt;{&lt;br /&gt;	var connection = context.Connection;&lt;br /&gt;	var command = connection.CreateCommand();&lt;br /&gt;	command.CommandText = sql; &lt;br /&gt;&lt;br /&gt;	try&lt;br /&gt;	{&lt;br /&gt;	    connection.Open();&lt;br /&gt;	    command.ExecuteNonQuery();&lt;br /&gt;	}&lt;br /&gt;	finally&lt;br /&gt;	{&lt;br /&gt;	    connection.Close();&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-7421858668941341967?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/7421858668941341967/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=7421858668941341967' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7421858668941341967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7421858668941341967'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2010/07/executing-sqlqueries-on-objectcontext.html' title='Executing SQLQueries on ObjectContext'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-4366199454563168932</id><published>2010-07-05T17:22:00.002+02:00</published><updated>2010-07-05T17:29:20.865+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><title type='text'>Handy Windows shortcut</title><content type='html'>&lt;div style="text-align: justify;"&gt;Sometimes it happens to me that I have to copy the path of a file to the clipboard and paste the it somewhere (console, visual studio, etc.); but it is not as easy to get the path as it is with folders where you can simply get it from windows explorer.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Windows has a hidden shortcut to get the path; when you press "shift" and click with the right mouse button on a file then in the context menu you get an additional entry which is called &lt;/div&gt;&lt;div style="text-align: justify;"&gt;"Als Pfad kopieren" or "Copy as path". Afterwards you can simply paste wherever you need it.&lt;/div&gt;&lt;div&gt;I find this feature extremely useful.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.petri.co.il/quickly_copy_file_and_folder_path_in_windows_vista.htm"&gt;Here you can find also some screenshots.&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-4366199454563168932?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/4366199454563168932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=4366199454563168932' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4366199454563168932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4366199454563168932'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2010/07/handy-windows-shortcut.html' title='Handy Windows shortcut'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-391391193178527416</id><published>2009-11-21T13:40:00.005+01:00</published><updated>2009-11-21T14:06:36.439+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows Vista'/><category scheme='http://www.blogger.com/atom/ns#' term='Hardware'/><title type='text'>USB 2.0 vs. Firewire 400 vs. eSATA</title><content type='html'>&lt;div style="text-align: justify;"&gt;To backup my data I bought the external harddisk &lt;a href="http://support.wdc.com/product/download.asp?groupid=111&amp;amp;lang=en"&gt;Western Digital My Book Home Edition&lt;/a&gt; with a capacity of 1 Terabyte which provides the following interfaces:&lt;br /&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;2 x Firewire 400&lt;/li&gt;&lt;li&gt;1 x USB 2.0&lt;/li&gt;&lt;li&gt;1 x eSATA&lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;As I was curious to see how big is the difference between these interfaces I did some performance testing.&lt;br /&gt;&lt;/div&gt;This are the results:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_ogsDq3H2JA0/Swfimd33NmI/AAAAAAAAAhU/NB9I02vfWDo/s1600/External+HDD+Speed+diagram.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 314px;" src="http://2.bp.blogspot.com/_ogsDq3H2JA0/Swfimd33NmI/AAAAAAAAAhU/NB9I02vfWDo/s400/External+HDD+Speed+diagram.jpg" alt="" id="BLOGGER_PHOTO_ID_5406539028163409506" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_ogsDq3H2JA0/SwfimpUIIwI/AAAAAAAAAhc/QpZbH_nb_5c/s1600/External+HDD+Speed.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 94px;" src="http://4.bp.blogspot.com/_ogsDq3H2JA0/SwfimpUIIwI/AAAAAAAAAhc/QpZbH_nb_5c/s400/External+HDD+Speed.jpg" alt="" id="BLOGGER_PHOTO_ID_5406539031234749186" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;I did the perfomance testing under Windows Vista 64bit edition with the tool &lt;a href="http://www.box.net/shared/bg90ehne4c"&gt;HDD Speed Test Tool&lt;/a&gt; by &lt;a href="http://www.oette.info/"&gt;Marko Oette&lt;/a&gt;.&lt;br /&gt;Regarding the eSATA interface I would like to say that the hot plug works (connect/disconnect while windows is running) and that while working with my computer I encountered sometimes some strange problems. The whole computer was blocked especially when I used applications that show an open file dialog or something similar. As soon as I unplugged the external HDD everything worked well. I would say that eSATA does not work 100%. This may be especially frustrating when making a backup of very large files and during the backup the HDD disappears (which happened to me). I don't exactly know if it is a driver, hardware or Windows Vista problem.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-391391193178527416?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/391391193178527416/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=391391193178527416' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/391391193178527416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/391391193178527416'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/11/usb-20-vs-firewire-400-vs-esata.html' title='USB 2.0 vs. Firewire 400 vs. eSATA'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_ogsDq3H2JA0/Swfimd33NmI/AAAAAAAAAhU/NB9I02vfWDo/s72-c/External+HDD+Speed+diagram.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-3970870821268541297</id><published>2009-11-21T12:24:00.007+01:00</published><updated>2009-11-21T14:55:16.317+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Search highlighting in WPF DataGrid</title><content type='html'>Unfortunately the DataGrid of the &lt;a href="http://wpf.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=29117"&gt;WPF-Toolkit&lt;/a&gt; does not provide a text highlighting feature out of the box; but sometimes it is very usefull for the users to be able to search for text or numbers in the datagrid to find the interesting information more quickly.&lt;br /&gt;Tomer Shamam did &lt;a href="http://blogs.microsoft.co.il/blogs/tomershamam/archive/2009/08/27/wpf-datagrid-search-and-highlight.aspx"&gt;a very good work&lt;/a&gt; which highlights a search key in different colors depending on which column they were found.&lt;br /&gt;&lt;br /&gt;The only things which I don't like on his solution are:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It works only if the datasource of the datagrid are objects&lt;/li&gt;&lt;li&gt;That you have to define a style for every property you want to be highlighted in the datagrid which may be a big work if you have 15 properties for example&lt;/li&gt;&lt;li&gt;When a row with a match is selected you do not see anymore which cell was highlighted&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div style="text-align: justify;"&gt;For my pupose I don't need the feature of the different coloring because I want only to highlight all cells in the datagrid where the search term is present in the same color. To resolve all of the above issues I changed the code of Shamam slightly.&lt;br /&gt;&lt;/div&gt;You still need this two helper classes written by Shamam:&lt;br /&gt;&lt;pre class="prettyprint"&gt;public class SearchTermConverter : IMultiValueConverter&lt;br /&gt;{&lt;br /&gt;public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)&lt;br /&gt;{&lt;br /&gt; var stringValue = values[0] == null ? string.Empty : values[0].ToString();&lt;br /&gt; var searchTerm = values[1] as string;&lt;br /&gt;&lt;br /&gt; return !string.IsNullOrEmpty(searchTerm) &amp;amp;&amp;amp;&lt;br /&gt;        !string.IsNullOrEmpty(stringValue) &amp;amp;&amp;amp;&lt;br /&gt;        stringValue.ToLower().Contains(searchTerm.ToLower());&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)&lt;br /&gt;{&lt;br /&gt; throw new NotSupportedException();&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;and&lt;br /&gt;&lt;pre class="prettyprint"&gt;public static class SearchOperations&lt;br /&gt;{&lt;br /&gt;public static string GetSearchTerm(DependencyObject obj)&lt;br /&gt;{&lt;br /&gt; return (string)obj.GetValue(SearchTermProperty);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static void SetSearchTerm(DependencyObject obj, string value)&lt;br /&gt;{&lt;br /&gt; obj.SetValue(SearchTermProperty, value);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static readonly DependencyProperty SearchTermProperty =&lt;br /&gt; DependencyProperty.RegisterAttached(&lt;br /&gt; "SearchTerm",&lt;br /&gt;     typeof(string),&lt;br /&gt;     typeof(SearchOperations),&lt;br /&gt;     new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.Inherits));&lt;br /&gt;&lt;br /&gt;public static bool GetIsMatch(DependencyObject obj)&lt;br /&gt;{&lt;br /&gt; return (bool)obj.GetValue(IsMatchProperty);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static void SetIsMatch(DependencyObject obj, bool value)&lt;br /&gt;{&lt;br /&gt; obj.SetValue(IsMatchProperty, value);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* Using a DependencyProperty as the backing store for IsMatch.  This enables animation, styling, binding, etc...*/&lt;br /&gt;public static readonly DependencyProperty IsMatchProperty =&lt;br /&gt; DependencyProperty.RegisterAttached("IsMatch", typeof(bool), typeof(SearchOperations), new UIPropertyMetadata(false));&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;As far as I understood this code defines a new dependancy property on the datagrid where the search term is stored and another dependancy property on each cell which stores wheter it is a match or not. Through the style which is defined in the Resource section of the page the "IsMatch" property is used to format the cell accordingly.&lt;br /&gt;&lt;/div&gt;This is my modified XAML code to search the text of the datagrid instead of the property. Here you can also change the different colors if you like.&lt;br /&gt;&lt;pre&gt;&amp;lt;Grid.Resources&amp;gt;&lt;br /&gt;&amp;lt;local:SearchTermConverter&lt;br /&gt;   x:Key="SearchTermConverter" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;SolidColorBrush&lt;br /&gt;   x:Key="{x:Static SystemColors.HighlightBrushKey}"&lt;br /&gt;   Color="Blue" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;SolidColorBrush&lt;br /&gt;   x:Key="HighlightColor"&lt;br /&gt;   Color="Yellow" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;SolidColorBrush&lt;br /&gt;   x:Key="SelectedHighlightedColor"&lt;br /&gt;   Color="Red" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;Style&lt;br /&gt;   x:Key="DefaultCell"&lt;br /&gt;   TargetType="{x:Type toolkit:DataGridCell}"&amp;gt;&lt;br /&gt;   &amp;lt;Setter&lt;br /&gt;       Property="local:SearchOperations.IsMatch"&amp;gt;&lt;br /&gt;       &amp;lt;Setter.Value&amp;gt;&lt;br /&gt;           &amp;lt;MultiBinding&lt;br /&gt;               Converter="{StaticResource SearchTermConverter}"&amp;gt;&lt;br /&gt;               &amp;lt;Binding&lt;br /&gt;                   RelativeSource="{RelativeSource Self}"&lt;br /&gt;                   Path="Content.Text" /&amp;gt;&lt;br /&gt;               &amp;lt;Binding&lt;br /&gt;                   RelativeSource="{RelativeSource Self}"&lt;br /&gt;                   Path="(local:SearchOperations.SearchTerm)" /&amp;gt;&lt;br /&gt;           &amp;lt;/MultiBinding&amp;gt;&lt;br /&gt;       &amp;lt;/Setter.Value&amp;gt;&lt;br /&gt;   &amp;lt;/Setter&amp;gt;&lt;br /&gt;   &amp;lt;Style.Triggers&amp;gt;&lt;br /&gt;       &amp;lt;Trigger&lt;br /&gt;           Property="local:SearchOperations.IsMatch"&lt;br /&gt;           Value="True"&amp;gt;&lt;br /&gt;           &amp;lt;Setter&lt;br /&gt;               Property="Background"&lt;br /&gt;               Value="{StaticResource HighlightColor}"&amp;gt;&lt;br /&gt;           &amp;lt;/Setter&amp;gt;&lt;br /&gt;       &amp;lt;/Trigger&amp;gt;&lt;br /&gt;       &amp;lt;MultiTrigger&amp;gt;&lt;br /&gt;           &amp;lt;MultiTrigger.Conditions&amp;gt;&lt;br /&gt;               &amp;lt;Condition&lt;br /&gt;                   Property="IsSelected"&lt;br /&gt;                   Value="True" /&amp;gt;&lt;br /&gt;               &amp;lt;Condition&lt;br /&gt;                   Property="local:SearchOperations.IsMatch"&lt;br /&gt;                   Value="True" /&amp;gt;&lt;br /&gt;           &amp;lt;/MultiTrigger.Conditions&amp;gt;&lt;br /&gt;           &amp;lt;Setter&lt;br /&gt;               Property="Background"&lt;br /&gt;               Value="{StaticResource SelectedHighlightedColor}"&amp;gt;&amp;lt;/Setter&amp;gt;&lt;br /&gt;       &amp;lt;/MultiTrigger&amp;gt;&lt;br /&gt;   &amp;lt;/Style.Triggers&amp;gt;&lt;br /&gt;&amp;lt;/Style&amp;gt;&lt;br /&gt;&amp;lt;/Grid.Resources&amp;gt;&lt;/pre&gt;&lt;br /&gt;Then the style is assigned to the datagrid:&lt;br /&gt;&lt;pre&gt;&amp;lt;toolkit:DataGrid&lt;br /&gt;AutoGenerateColumns="True"&lt;br /&gt;Name="dgvDataTable"&lt;br /&gt;&lt;b&gt;CellStyle="{StaticResource DefaultCell}"&lt;/b&gt;&lt;br /&gt;Margin="0,256,0,0"&lt;br /&gt;Background="White" /&amp;gt;&lt;/pre&gt;&lt;br /&gt;And finally the textbox connected to the "SearchTerm" property of the datagrid;&lt;br /&gt;either via code in the TextChanged event of the TextBox:&lt;br /&gt;&lt;pre class="prettyprint"&gt;SearchOperations.SetSearchTerm(this.dgvObjects, this.textBox1.Text);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;or via XAML:&lt;br /&gt;&lt;pre&gt;&amp;lt;Window&lt;br /&gt;    x:Class="SearchHighlighting.Window1"&lt;br /&gt;    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&lt;br /&gt;    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&lt;br /&gt;    Title="Window1"&lt;br /&gt;    Height="460.138"&lt;br /&gt;    Width="502"&lt;br /&gt;    xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit"&lt;br /&gt;    &lt;b&gt;xmlns:local="clr-namespace:SearchHighlighting"&lt;/b&gt;&amp;gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;toolkit:DataGrid&lt;br /&gt;    AutoGenerateColumns="True"&lt;br /&gt;    Name="dgvDataTable"&lt;br /&gt;    CellStyle="{StaticResource DefaultCell}"&lt;br /&gt;    Margin="0,256,0,0"&lt;br /&gt;    Background="White"&lt;br /&gt;    &lt;b&gt;local:SearchOperations.SearchTerm="{Binding ElementName=textBox1, Path=Text}"&lt;/b&gt; /&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The result looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_ogsDq3H2JA0/SwfT30urDZI/AAAAAAAAAhM/UHf1ysE5vJw/s1600/search_highlighting.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 367px;" src="http://4.bp.blogspot.com/_ogsDq3H2JA0/SwfT30urDZI/AAAAAAAAAhM/UHf1ysE5vJw/s400/search_highlighting.jpg" alt="" id="BLOGGER_PHOTO_ID_5406522833682238866" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can download the whole project from &lt;a href="http://cid-3a56bb5e7150e222.skydrive.live.com/self.aspx/.Public/SearchHighlighting.zip"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-3970870821268541297?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/3970870821268541297/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=3970870821268541297' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3970870821268541297'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3970870821268541297'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/11/search-highlighting-in-wpf-datagrid.html' title='Search highlighting in WPF DataGrid'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_ogsDq3H2JA0/SwfT30urDZI/AAAAAAAAAhM/UHf1ysE5vJw/s72-c/search_highlighting.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-4807592149707719826</id><published>2009-11-17T19:52:00.011+01:00</published><updated>2009-11-21T11:42:33.228+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>SQL Server and legacy systems</title><content type='html'>&lt;div style="text-align: justify;"&gt;Sometimes it happenes that we have to format the data which is stored in an SQL Server Database for an older system which requires the data to have a specific length. To achieve the length different datatypes are filled differently (at least in my case).&lt;br /&gt;&lt;/div&gt;Lets take this example (we assume a length of 8):&lt;br /&gt;- numbers have to be filled with zeros on the left (e.g. 66 -&gt; 000066)&lt;br /&gt;- strings have to be filled with spaces on the right (e.g. 'abc' -&gt; 'abc     ')&lt;br /&gt;&lt;br /&gt;How can we achieve this?&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Well the first problem is that we have to measure the length of the data and SQL Server provides two functions for that: 'LEN' and 'DATALENGTH'&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This is not a problem you would say but it is because they behave differently. Look at the following examples:&lt;br /&gt;&lt;/div&gt;Note the leading and trailing spaces of the strings!&lt;br /&gt;"SELECT LEN(' abc ')" =&gt; 4&lt;br /&gt;"SELECT DATALENGTH(' abc ')" =&gt; 5&lt;br /&gt;&lt;br /&gt;"SELECT LEN(123)" =&gt; 3&lt;br /&gt;"SELECT LEN(123.4567)" =&gt; 8&lt;br /&gt;&lt;br /&gt;"SELECT DATALENGTH(123)" =&gt; 4&lt;br /&gt;"SELECT DATALENGTH(999999999999)" =&gt; 9&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Well this "strange" behaviour is because of what these functions do. Let's see the definition from MSDN on this:&lt;br /&gt;&lt;/div&gt;&lt;blockquote&gt;LEN (Transact-SQL)Returns the number of characters of the specified string expression, trailing blanks.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;DATALENGTH (Transact-SQL)&lt;br /&gt;Returns the number of bytes used to represent any expression.&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;So in principle I would say: if you want to know the number of characters of a value then you should use DATALENGTH for string values ( nchar, text, nvarchar,...) and LEN for numbers (int, float, decimal,...).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The next problem when filling values is the NULL value. According to the definition of the two functions is LEN(NULL) equal to NULL and DATALENGTH(NULL) also NULL. This may be a problem since I have to provide blanks or zeros if the value is NULL (e.g. '        ', 00000000).&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The third problem is on how to fill the value with the requested fillers (zeros and blanks)? Well for this SQL Server provides a very nice function: REPLICATE&lt;br /&gt;&lt;/div&gt;This function takes as input a character which should be replicated and a length. E.g.:&lt;br /&gt;&lt;pre&gt;"SELECT REPLICATE('0', 10)" =&gt; 0000000000&lt;br /&gt;"SELECT REPLICATE(' ', 10)" =&gt; '          '&lt;/pre&gt;This helps us to create what we want. So if we have the number '99' and we want it to fill on the left to a length of 8 we can do something like:&lt;br /&gt;&lt;pre&gt;"SELECT REPLICATE('0', 8 - LEN(99)) + CAST(99 AS NCHAR)" =&gt; 00000099&lt;br /&gt;"SELECT REPLICATE(' ', 8 - DATALENGTH(' abc ')) + ' abc '" =&gt; '    abc '&lt;/pre&gt;To fill on the right we have another possibility; it is casted to an NCHAR of the desired length; but this fills only with blanks:&lt;br /&gt;&lt;pre&gt;"SELECT CAST(' abc ' AS NCHAR(8))" =&gt; ' abc    '&lt;br /&gt;"SELECT CAST(99 AS NCHAR(8))" =&gt; '99      '&lt;/pre&gt;If you want to fill with something different then you have to use again the REPLICATE function as described above.&lt;br /&gt;&lt;br /&gt;To handle the NULL value we use the case statement:&lt;br /&gt;"SELECT CASE WHEN(&lt;span style="font-weight: bold;"&gt;null&lt;/span&gt; IS NOT NULL) THEN REPLICATE('0', 8 - LEN(&lt;span style="font-weight: bold;"&gt;null&lt;/span&gt;)) + CAST(&lt;span style="font-weight: bold;"&gt;null&lt;/span&gt; AS NCHAR) ELSE REPLICATE('0', 8) END" =&gt; '00000000'&lt;br /&gt;&lt;br /&gt;"SELECT CASE WHEN(&lt;span style="font-weight: bold;"&gt;99&lt;/span&gt; IS NOT NULL) THEN REPLICATE('0', 8 - LEN(&lt;span style="font-weight: bold;"&gt;99&lt;/span&gt;)) + CAST(&lt;span style="font-weight: bold;"&gt;99&lt;/span&gt; AS NCHAR) ELSE REPLICATE('0', 8) END" =&gt; '00000099'&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Of course written like this it does not make much sense since we know in advance which part of the case statement is executed; but imagine you write in the place of the "null" or "99" the name of a column, then it makes perfectly sense. You can now easily write a case statement for string values.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-4807592149707719826?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/4807592149707719826/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=4807592149707719826' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4807592149707719826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4807592149707719826'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/11/sql-server-and-legacy-systems.html' title='SQL Server and legacy systems'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-7747835084706055237</id><published>2009-11-03T17:40:00.002+01:00</published><updated>2009-11-03T17:52:17.763+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><title type='text'>Capturing Google Earth flight</title><content type='html'>&lt;div style="text-align: justify;"&gt;Recently I created a photoshow from my photos of the summer and there I wanted also to add a &lt;a href="http://earth.google.com/"&gt;Google Earth&lt;/a&gt; flight, so that everybody has an idea where this location is; and also because its simply cool :-)&lt;br /&gt;&lt;br /&gt;On the internet they say that the pro edition has such a functionality but it costs 400$.&lt;br /&gt;I tried then severeal screen capturing tools &lt;a href="http://camstudio.org/"&gt;CamStudio&lt;/a&gt; or &lt;a href="http://www.wisdom-soft.com/asr/asr_free.htm"&gt;AutoScreenRecorder&lt;/a&gt;. They may be good to capture the screen to show other people how to perform some actions but for the Google Earth flight they are too slow. If they are capturing the flight isn't smoothly anymore.&lt;br /&gt;Fortunately I found a very good tool which is also used to capture games. It is called &lt;a href="http://www.fraps.com/download.php"&gt;Fraps&lt;/a&gt; and does a very very good job. I tried it with the OpenGL as well as with the DirectX mode of Google Earth and it works well with both of them. I think that after the test period it makes a watermark on the video but I can live with that.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-7747835084706055237?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/7747835084706055237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=7747835084706055237' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7747835084706055237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7747835084706055237'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/11/capturing-google-earth-flight.html' title='Capturing Google Earth flight'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-1028515590221429776</id><published>2009-09-29T21:01:00.006+02:00</published><updated>2009-09-29T21:30:34.501+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='Entity Framework'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>Full text search for Entity Framework</title><content type='html'>&lt;div style="text-align: justify;"&gt;Recently I played a bit with the "new" Entity Framework (basically the Object Relational mapper of Microsoft). It seems to be made quite good and it makes it very easy to work with objects in your application without having to map them back and forth from and to SQL. Also the possibility to launch LINQ queries over the data is very interesting because this avoids many errors and improves usability.&lt;br /&gt;But I missed something: a fulltext search.&lt;br /&gt;SQL Server has a very good fulltext search integrated and it would be nice to be able to perform queries through LINQ with it; but since Microsoft wanted to support also other database management systems they had to use only standard SQL for their mappings.&lt;br /&gt;&lt;br /&gt;Faced with this problem I resolved it by writing my own pseudo fulltext search by using the possibility of creating dynamic LINQ queries.&lt;br /&gt;First I will show You the code and then I explain a bit what I have done.&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Linq.Expressions;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Reflection;&lt;br /&gt;using System.Data.Objects;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public static class ObjectContextExtensions&lt;br /&gt;{&lt;br /&gt;/*&lt;br /&gt;  /// &amp;lt;summary&amp;gt;&lt;br /&gt;  /// Searches in all string properties for the specifed search key.&lt;br /&gt;  /// It is also able to search for several words. If the searchKey is for example 'John Travolta' then&lt;br /&gt;  /// all records which contain either 'John' or 'Travolta' in some string property&lt;br /&gt;  /// are returned.&lt;br /&gt;  /// &amp;lt;/summary&amp;gt;&lt;br /&gt;  /// &amp;lt;typeparam name="T"&amp;gt;&amp;lt;/typeparam&amp;gt;&lt;br /&gt;  /// &amp;lt;param name="query"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;  /// &amp;lt;param name="searchKey"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;  /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;*/&lt;br /&gt;  public static IQueryable&amp;lt;T&amp;gt; FullTextSearch&amp;lt;T&amp;gt;(this IQueryable&amp;lt;T&amp;gt; queryable, string searchKey)&lt;br /&gt;  {&lt;br /&gt;      return FullTextSearch&amp;lt;T&amp;gt;(queryable, searchKey, false);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt;  /// &amp;lt;summary&amp;gt;&lt;br /&gt;  /// Searches in all string properties for the specifed search key.&lt;br /&gt;  /// It is also able to search for several words. If the searchKey is for example 'John Travolta' then&lt;br /&gt;  /// with exactMatch set to false all records which contain either 'John' or 'Travolta' in some string property&lt;br /&gt;  /// are returned.&lt;br /&gt;  /// &amp;lt;/summary&amp;gt;&lt;br /&gt;  /// &amp;lt;typeparam name="T"&amp;gt;&amp;lt;/typeparam&amp;gt;&lt;br /&gt;  /// &amp;lt;param name="query"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;  /// &amp;lt;param name="searchKey"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;  /// &amp;lt;param name="exactMatch"&amp;gt;Specifies if only the whole word or every single word should be searched.&amp;lt;/param&amp;gt;&lt;br /&gt;  /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;*/&lt;br /&gt;  public static IQueryable&amp;lt;T&amp;gt; FullTextSearch&amp;lt;T&amp;gt;(this IQueryable&amp;lt;T&amp;gt; queryable, string searchKey, bool exactMatch)&lt;br /&gt;  {&lt;br /&gt;      ParameterExpression parameter = Expression.Parameter(typeof(T), "c");&lt;br /&gt;&lt;br /&gt;      MethodInfo containsMethod = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });&lt;br /&gt;      MethodInfo toStringMethod = typeof(object).GetMethod("ToString", new Type[] { });&lt;br /&gt;&lt;br /&gt;      var publicProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).Where(p =&amp;gt; p.PropertyType == typeof(string));&lt;br /&gt;      Expression orExpressions = null;&lt;br /&gt;&lt;br /&gt;      string[] searchKeyParts;&lt;br /&gt;      if (exactMatch)&lt;br /&gt;      {&lt;br /&gt;          searchKeyParts = new[] { searchKey };&lt;br /&gt;      }&lt;br /&gt;      else&lt;br /&gt;      {&lt;br /&gt;          searchKeyParts = searchKey.Split(' ');&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      foreach (var property in publicProperties)&lt;br /&gt;      {&lt;br /&gt;          Expression nameProperty = Expression.Property(parameter, property);&lt;br /&gt;          foreach (var searchKeyPart in searchKeyParts)&lt;br /&gt;          {&lt;br /&gt;              Expression searchKeyExpression = Expression.Constant(searchKeyPart);&lt;br /&gt;              Expression callContainsMethod = Expression.Call(nameProperty, containsMethod, searchKeyExpression);&lt;br /&gt;              if (orExpressions == null)&lt;br /&gt;              {&lt;br /&gt;                  orExpressions = callContainsMethod;&lt;br /&gt;              }&lt;br /&gt;              else&lt;br /&gt;              {&lt;br /&gt;                  orExpressions = Expression.Or(orExpressions, callContainsMethod);&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      MethodCallExpression whereCallExpression = Expression.Call(&lt;br /&gt;          typeof(Queryable),&lt;br /&gt;          "Where",&lt;br /&gt;          new Type[] { queryable.ElementType },&lt;br /&gt;          queryable.Expression,&lt;br /&gt;          Expression.Lambda&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt;(orExpressions, new ParameterExpression[] { parameter }));&lt;br /&gt;&lt;br /&gt;      return queryable.Provider.CreateQuery&amp;lt;T&amp;gt;(whereCallExpression);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;I created this method as an extension method for an IQueryable&amp;lt;T&amp;gt;.&lt;br /&gt;This means if you have your ObjectContext (from the Entity Framework) then when accessing all objects of some type e.g. "context.Customers" then this returns an IQueryable&amp;lt;Customers&amp;gt;&lt;br /&gt;This means that You can call the above method like:&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;context.Customers.FullTextSearch("serachkey");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;or&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;context.Customers.FullTextSearch("searchkey", true);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;which searches only for whole words also if they contain spaces. This gives You then again an IQueryable&amp;lt;Customers&amp;gt; which contains only the filtered objects.&lt;br /&gt;&lt;br /&gt;Ok. Now something about the code.&lt;br /&gt;This method "simply" creates a lambda expression which gets all the string properties of the type T, calls the "Contains" method with the search key as parameter on them and connects them with an OR. This means that it would be similar to do something like:&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;context.Customers.Where(c =&gt; c.FirstName.Contains("searchkey") || c.LastName.Contains("searchkey") || c.Street.Contains("searchkey") || ...);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But this can become a very long, nasty and error prone task if You have for example 30 string columns. Exactly because of this I wrote this code :-)&lt;br /&gt;&lt;br /&gt;Hope this helps You...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-1028515590221429776?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/1028515590221429776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=1028515590221429776' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/1028515590221429776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/1028515590221429776'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/09/full-text-search-for-entity-framework.html' title='Full text search for Entity Framework'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-6078636825865396851</id><published>2009-08-13T11:52:00.013+02:00</published><updated>2009-09-01T17:02:22.625+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>LINQ, Expression trees and ORMapper</title><content type='html'>&lt;div style="text-align: justify;"&gt;In response to the question of Jonathan of my post on expression trees I will post here some code on how an expression tree can be analyzed and used to create your own object relational mapper.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The core of the app is the expression tree visitor. Practically it traverses all the expressions of a LINQ expression and creates the appropriate SQL instructions for it. To get the correct column and table names it uses an interface called IMappingProvider which makes it possible to have different mapping providers. I created an AttributeMappingProvider which provides the mapping by defining attributes on the classes and properties, an XmlMappingProvider which reads the mapping information from an XML file and a DBMappingProvider which reads from a table in a database. My ORMapper is able to create Select and Delete queries by specifying a LINQ expression as where clause.&lt;br /&gt;&lt;br /&gt;But enough theory; here is some code :-)&lt;br /&gt;This is the core method which dispatches the incoming expression and calls the appropriate method:&lt;br /&gt;&lt;pre class="prettyprint"&gt;/* /// &amp;lt;summary&amp;gt;&lt;br /&gt;/// This method is the dispatcher for the different expression types.&lt;br /&gt;/// NOTE: not all expression types are considered.&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;param name="expression"&amp;gt;The expression.&amp;lt;/param&amp;gt;&lt;br /&gt;/// &amp;lt;param name="sql"&amp;gt;The SQL string builder.&amp;lt;/param&amp;gt;&lt;br /&gt;/// &amp;lt;param name="isOnRightSide"&amp;gt;Tells if the expression is on the right hand side. Necessary for some expression evaluations.&amp;lt;/param&amp;gt; */&lt;br /&gt;private object VisitExpression(Expression expression, StringBuilder sql, bool isOnRightSide)&lt;br /&gt;{&lt;br /&gt;  LambdaExpression lambdaExpression = expression as LambdaExpression;&lt;br /&gt;  BinaryExpression binaryExpression = expression as BinaryExpression;&lt;br /&gt;  MemberExpression memberExpression = expression as MemberExpression;&lt;br /&gt;  ConstantExpression constantExpression = expression as ConstantExpression;&lt;br /&gt;  UnaryExpression unaryExpression = expression as UnaryExpression;&lt;br /&gt;  MethodCallExpression methodCallExpression = expression as MethodCallExpression;&lt;br /&gt;  ParameterExpression parameterExpression = expression as ParameterExpression;&lt;br /&gt;&lt;br /&gt;  if (lambdaExpression != null)&lt;br /&gt;  {&lt;br /&gt;      VisitExpression(lambdaExpression.Body, sql, false);&lt;br /&gt;  }&lt;br /&gt;  else if (binaryExpression != null)&lt;br /&gt;  {&lt;br /&gt;      VisitBinaryExpression(sql, binaryExpression);&lt;br /&gt;  }&lt;br /&gt;  else if (memberExpression != null)&lt;br /&gt;  {&lt;br /&gt;      return VisitMemberExpression(sql, isOnRightSide, memberExpression);&lt;br /&gt;  }&lt;br /&gt;  else if (constantExpression != null)&lt;br /&gt;  {&lt;br /&gt;      VisitConstantExpression(sql, constantExpression);&lt;br /&gt;  }&lt;br /&gt;  else if (unaryExpression != null)&lt;br /&gt;  {&lt;br /&gt;      VisitUnaryExpression(sql, unaryExpression);&lt;br /&gt;  }&lt;br /&gt;  else if (methodCallExpression != null)&lt;br /&gt;  {&lt;br /&gt;      VisitMethodCallExpression(sql, methodCallExpression);&lt;br /&gt;  }&lt;br /&gt;  else if (parameterExpression != null)&lt;br /&gt;  {&lt;br /&gt;      VisitParameterExpression(sql, parameterExpression);&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;      throw new NotSupportedException(string.Format("The '{0}' is not supported!", expression.GetType().Name));&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return null;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Let's take for example the method to analyze a binary expression:&lt;br /&gt;&lt;pre class="prettyprint"&gt;private void VisitBinaryExpression(StringBuilder sql, BinaryExpression binaryExpression)&lt;br /&gt;{&lt;br /&gt;  sql.Append("(");&lt;br /&gt;  VisitExpression(binaryExpression.Left, sql, false);&lt;br /&gt;  sql.Append(GetOperandFromExpression(binaryExpression));&lt;br /&gt;  VisitExpression(binaryExpression.Right, sql, true);&lt;br /&gt;  sql.Append(") ");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can see here that for binary expressions (e.g. =, &amp;amp;&amp;amp;, ||) I always open a parenthesis; this creates also unnecessary parenthesis, but makes sure that boolean conditions are evaluated correctly. Then the left expression is evaluated, the operator is added, the right expression is evaluated and finally a closing parenthesis is added.&lt;br /&gt;This is the dispatcher method for the operators:&lt;br /&gt;&lt;pre class="prettyprint"&gt;/* /// &amp;lt;summary&amp;gt;&lt;br /&gt;/// This method is the dispatcher for the operands.&lt;br /&gt;/// NOTE: not all operands are implemented!&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;/// &amp;lt;param name="expression"&amp;gt;The expression to dispatch.&amp;lt;/param&amp;gt;&lt;br /&gt;/// &amp;lt;returns&amp;gt;The appropriate SQL operand.&amp;lt;/returns&amp;gt;*/&lt;br /&gt;private string GetOperandFromExpression(Expression expression)&lt;br /&gt;{&lt;br /&gt;  string operand = string.Empty;&lt;br /&gt;  switch (expression.NodeType)&lt;br /&gt;  {&lt;br /&gt;      case ExpressionType.And:&lt;br /&gt;          operand = "AND";&lt;br /&gt;          break;&lt;br /&gt;      case ExpressionType.AndAlso:&lt;br /&gt;          operand = "AND";&lt;br /&gt;          break;&lt;br /&gt;      case ExpressionType.Equal:&lt;br /&gt;          operand = "=";&lt;br /&gt;          break;&lt;br /&gt;      case ExpressionType.ExclusiveOr:&lt;br /&gt;          operand = "OR";&lt;br /&gt;          break;&lt;br /&gt;      case ExpressionType.GreaterThan:&lt;br /&gt;          operand = "&amp;gt;";&lt;br /&gt;          break;&lt;br /&gt;      case ExpressionType.GreaterThanOrEqual:&lt;br /&gt;          operand = "&amp;gt;=";&lt;br /&gt;          break;&lt;br /&gt;      case ExpressionType.Not:&lt;br /&gt;          operand = "NOT";&lt;br /&gt;          break;&lt;br /&gt;      case ExpressionType.NotEqual:&lt;br /&gt;          operand = "&amp;lt;&amp;gt;";&lt;br /&gt;          break;&lt;br /&gt;      case ExpressionType.Or:&lt;br /&gt;          operand = "OR";&lt;br /&gt;          break;&lt;br /&gt;      case ExpressionType.OrElse:&lt;br /&gt;          operand = "OR";&lt;br /&gt;          break;&lt;br /&gt;      default:&lt;br /&gt;          throw new NotImplementedException();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return operand + " ";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To get the correct string to add to the sql query I wrote a little method which performs also escaping of the single quote. Additionally it calls the to string method with the invariant culture if the object supports it.&lt;br /&gt;&lt;pre class="prettyprint"&gt;private string FormatValue(object value)&lt;br /&gt;{&lt;br /&gt;  if(value == null || value == DBNull.Value)&lt;br /&gt;  {&lt;br /&gt;    return "NULL";&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  string stringValue = value.ToString();&lt;br /&gt;  var invariantMethod = value.GetType().GetMethod("ToString", new Type[] { typeof(CultureInfo) });&lt;br /&gt;  if (invariantMethod != null)&lt;br /&gt;  {&lt;br /&gt;      stringValue = (string)invariantMethod.Invoke(value, new object[] { CultureInfo.InvariantCulture });&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  stringValue = stringValue.Replace("'", "''");&lt;br /&gt;&lt;br /&gt;  if (value is string || value is DateTime)&lt;br /&gt;  {&lt;br /&gt;      return string.Format("'{0}'", stringValue);&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;      return stringValue;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To test all this I created a little sample application and a sample class. The customer class supports the AttributeMappingProvider and specifies the mapping on the class and propeties:&lt;br /&gt;&lt;pre class="prettyprint"&gt;[DBTable("cust")]&lt;br /&gt;class Customer&lt;br /&gt;{&lt;br /&gt;    [DBField("nam")]&lt;br /&gt;    public string Name { get; set; }&lt;br /&gt;&lt;br /&gt;    [DBField("num")]&lt;br /&gt;    public int Age { get; set; }&lt;br /&gt;&lt;br /&gt;    [DBField("height")]&lt;br /&gt;    public int Height;&lt;br /&gt;&lt;br /&gt;    [DBField("surname")]&lt;br /&gt;    public string Surname;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To get some results I wrote this code:&lt;br /&gt;&lt;pre class="prettyprint"&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;    ORMapper mapper = new ORMapper();&lt;br /&gt;    var c1 = new Customer{Name = "cus2"};&lt;br /&gt;    var selectQuery = mapper.Select&amp;lt;Customer&amp;gt;(c =&amp;gt; c.Name == "hallo" &amp;&amp; c.Age == 12 || c.Name == c1.Name &amp;&amp; c.Name == 4.ToString() &amp;&amp; c.Name.Contains("aaa"));&lt;br /&gt;    var deleteQuery = mapper.Delete&amp;lt;Customer&amp;gt;(c =&amp;gt; c.Name == "hallo" &amp;&amp; c.Age == 12 || c.Name == c1.Name &amp;&amp; c.Name == 4.ToString() &amp;&amp; c.Name.Contains("aaa"));&lt;br /&gt;    Console.WriteLine(selectQuery);&lt;br /&gt;    Console.WriteLine(deleteQuery);&lt;br /&gt;    Console.ReadLine();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;which outputs this:&lt;br /&gt;&lt;pre class="prettyprint"&gt;SELECT * FROM cust WHERE (((nam = 'hallo') AND (num = 12)) OR ((((nam = 'cus2') AND (nam = '4')) AND (nam LIKE '%aaa%')) AND (height = 10)));&lt;br /&gt;&lt;br /&gt;DELETE FROM cust WHERE (((nam = 'hallo') AND (num = 12)) OR (((nam = 'cus2') AND (nam = '4')) AND (nam LIKE '%aaa%')));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can cahnge the mapping provider in the constructor of the ORMapper.&lt;br /&gt;A sample file for the XmlAttributeMapper is also included. Here the mapping is specified like this:&lt;br /&gt;&lt;pre class="prettyprint"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br /&gt;&amp;lt;mapping&amp;gt;&lt;br /&gt;  &amp;lt;Customer table="tbl_cus"&amp;gt;&lt;br /&gt;    &amp;lt;map property="Name" column="cus_nam"&amp;gt;&amp;lt;/map&amp;gt;&lt;br /&gt;    &amp;lt;map property="Age" column="cus_age"&amp;gt;&amp;lt;/map&amp;gt;&lt;br /&gt;  &amp;lt;/Customer&amp;gt;&lt;br /&gt;&amp;lt;/mapping&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I did not test the DBMappingProvider, but You can easily adapt it to your needs.&lt;br /&gt;&lt;br /&gt;You can download the project and source code files from &lt;a href="http://manfred.ramoser.googlepages.com/ORMapper.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-6078636825865396851?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/6078636825865396851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=6078636825865396851' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/6078636825865396851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/6078636825865396851'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/08/linq-expression-trees-and-ormapper.html' title='LINQ, Expression trees and ORMapper'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-3582805699050459935</id><published>2009-06-25T17:25:00.008+02:00</published><updated>2009-06-26T22:16:50.049+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>NumericUpDown validation</title><content type='html'>&lt;div style="text-align: justify;"&gt;Today I had the problem that I had to set up input validation on an edit form. Among other controls there was also a NumericUpDown (NUD) control and I thought: well if I specifiy the min value and the max value then the user is not able to input a wrong value;&lt;br /&gt;&lt;/div&gt;This code prints the current value of the NUD to a message box:&lt;br /&gt;&lt;pre class="prettyprint"&gt;MessageBox.Show(this.numericUpDown1.Value.ToString());&lt;/pre&gt;You can see an example for this in the following screenshot:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_ogsDq3H2JA0/SkOY19xrCSI/AAAAAAAAAVQ/q6ANPlUVsz8/s1600-h/nud.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 300px; height: 301px;" src="http://4.bp.blogspot.com/_ogsDq3H2JA0/SkOY19xrCSI/AAAAAAAAAVQ/q6ANPlUVsz8/s400/nud.jpg" alt="" id="BLOGGER_PHOTO_ID_5351288835129674018" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This works fine, but there is one exception. It is also possible to leave the NUD blank. If you show then the value of the NUD again with the above code then you get the last value that was present in the NUD control; as shown below:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_ogsDq3H2JA0/SkOY2F9EGjI/AAAAAAAAAVY/29aSMC0J7rI/s1600-h/nud1.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 299px; height: 301px;" src="http://2.bp.blogspot.com/_ogsDq3H2JA0/SkOY2F9EGjI/AAAAAAAAAVY/29aSMC0J7rI/s400/nud1.jpg" alt="" id="BLOGGER_PHOTO_ID_5351288837324937778" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This can also be explained. The value property of the NUD control is of type decimal in order to deal with the different types of numbers. The problem is that it is of type decimal and not decimal? (this is the &lt;a href="http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx"&gt;nullable&lt;/a&gt; version of decimal) and therefore it has to have value. Now is the question which value to set if the control is empty: 0, -1, decimal.MinValue or decimal.MaxValue?? None of these value really expresses what the user has entered; namely nothing.&lt;br /&gt;In a forum in the internet I read that a workaround for this issue is to check the Text property of the NUD control; but as you can see below the NUD control does not have such a property!!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_ogsDq3H2JA0/SkObmqLlQrI/AAAAAAAAAVw/STivroVg1Z0/s1600-h/nud2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 357px; height: 190px;" src="http://1.bp.blogspot.com/_ogsDq3H2JA0/SkObmqLlQrI/AAAAAAAAAVw/STivroVg1Z0/s400/nud2.png" alt="" id="BLOGGER_PHOTO_ID_5351291870706483890" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Fortunately there exists a solution to this problem. If you want to check if the user has entered a number into the NUD control you can use this code to check this:&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;if (string.IsNullOrEmpty(((Control)this.numericUpDown1).Text))&lt;br /&gt;{&lt;br /&gt; /* the user entered nothing */&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt; /* the NUD contains a valid number */&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-3582805699050459935?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/3582805699050459935/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=3582805699050459935' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3582805699050459935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3582805699050459935'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/06/numericupdown-validation.html' title='NumericUpDown validation'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_ogsDq3H2JA0/SkOY19xrCSI/AAAAAAAAAVQ/q6ANPlUVsz8/s72-c/nud.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-8663840730078649729</id><published>2009-06-24T19:13:00.003+02:00</published><updated>2009-06-24T19:33:17.810+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>HTML parsing</title><content type='html'>&lt;div style="text-align: justify;"&gt;In a very small personal project I needed to parse an HTML page. I thought that HTML = XML and so I tried to load the response string into an XDocument; but I was too optimistic. I got a lot of errors from the XDocument.Parse() method. I read on the internet that it is only possible to do this if the web page is XHTML and follows all the standards. But there are a lot of web pages out there which never heard nothing about standards. A good example are pages from Microsoft. This page of the &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb842062.aspx"&gt;Sysinternals Suite&lt;/a&gt; for example produces 53 errors and 14 warnings when validating it with the &lt;a href="http://validator.w3.org/"&gt;W3C validator&lt;/a&gt;!!&lt;br /&gt;&lt;br /&gt;There is a solution to the HTML parsing problem for C#. There exists a project called &lt;a href="http://www.codeplex.com/htmlagilitypack"&gt;HTML Agility Pack&lt;/a&gt; on CodePlexx which provides a mechanism to parse an HTML string and to navigate it like ian XmlDocument. It works great but it does not provide support for LINQ queries which is very nasty if you are accustomed to it (like me :-))&lt;br /&gt;But also for this exists a solution. Since the source code of the HTML Agility Pack is open for everyone &lt;a href="http://vijay.screamingpens.com/Articles/About.aspx"&gt;Vijay Santhanam&lt;/a&gt; created the ToXDocument() method, which converts the HtmlDocument to XDocument. This is then queryable with LINQ to XML. The post about this and a link to his project can be found &lt;a href="http://vijay.screamingpens.com/archive/2008/05/26/linq-amp-lambda-part-3-html-agility-pack-to-linq.aspx"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;It would be nice if they would add direct LINQ support to their HtmlDocument class but maybe they will do so in the future...&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-8663840730078649729?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/8663840730078649729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=8663840730078649729' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/8663840730078649729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/8663840730078649729'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/06/html-parsing.html' title='HTML parsing'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2103560138650583539</id><published>2009-06-18T17:54:00.003+02:00</published><updated>2009-06-18T18:03:37.958+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Reflection</title><content type='html'>&lt;div style="text-align: justify;"&gt;While trying to speed up an application I searched the internet for information about reflection. I use reflection quite often when I have to write a special XML serializer or when I have to write a simple OR mapper. The problem is that it is slow. I understand now also because you have to specify the type when you use the XmlSerializer of the .Net framework. Internally it generates IL code which speeds up the serialization a lot because the intermediate code is much faster than direct reflection.&lt;br /&gt;&lt;/div&gt;Regarding this problem I found a very interesting blog post which you can check out &lt;a href="http://theinstructionlimit.com/?p=76"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;div style="text-align: justify;"&gt;There a comparison is made between the direct reflection, reflection by using Reflection.Emit and by caching Reflection.Emit operations. As you can see there from the test results the cached reflection is about 8 times faster!! This may not be of importance if you serialize only 100 objects but if you serialize thousands or millions of objects than this makes a big difference.&lt;br /&gt;&lt;/div&gt;I tried his code in a project of mine where I use quite a lot reflection and indeed the operation finished about 6 times faster!&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you do a lot of reflection in your projects you should definitely give a look at this code. It's worth...&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2103560138650583539?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2103560138650583539/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2103560138650583539' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2103560138650583539'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2103560138650583539'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/06/reflection.html' title='Reflection'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-5716219127942039140</id><published>2009-06-15T17:52:00.003+02:00</published><updated>2009-06-15T18:09:56.868+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Performance</title><content type='html'>&lt;div style="text-align: justify;"&gt;Today I had to solve a common problem. The customer sad that the application is too slow; substantially the data import from an XML file into the object model is too slow. As every developer knows, performance problems are very nasty and it means also that you have to break your nice object oriented structure to gain some performance boosts :-(&lt;br /&gt;So I searched in the imort routine for code parts which can be optimized. I was able to change some code but that brought only a very small performance gain.&lt;br /&gt;After some time I decided to switch off the logging that states how many percent of the elements were already imported. That message was written to the console window and since the operation required about 15 seconds it was interesting to see at which point the import is.&lt;br /&gt;Then the surprise. After switching off the logging the data was imported in about 1,3 seconds. I knew that writing to the console is slow but that it is so slow...&lt;br /&gt;To solve this problem now I tried first to use an asynchronous event logging. It worked also quite well, but when the data was already loaded and displayed the logger wrote for some seconds longer to the console by indicating that 97% of the data was loaded now.&lt;br /&gt;This was also not a choice. Then I decided that it would be a good idea to switch off logging when running in release mode and turn it on when running in debug mode. So I have all informations on hand whenn looking for errors and the performance for the customer.&lt;br /&gt;To realize this I implemented in my logger a the method "LogDebugEvent" and "decorated" it with the "Conditional" attribute:&lt;br /&gt;&lt;pre class="prettyprint"&gt;[Conditional("DEBUG")]&lt;br /&gt;public void LogDebugEvent(LogLevel logLevel, string message, params object[] args)&lt;br /&gt;{&lt;br /&gt;  /* some code here*/&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This means that the compiler decides if the method call is executed or not. If you compile in Release mode than all calls to this method are removed from the code as if they do not exist. If you run in Debug mode then all calls are executed. This can be very usefull especially if you have code which slows down your program and is only for debug purposes.&lt;br /&gt;Important is that it matches exactly the constant that you want to use. It is casesensitive!! In the case of debug it is as you can see in the example above "DEBUG".&lt;br /&gt;&lt;br /&gt;More informations about the ConditionalAttribute can be found &lt;a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.conditionalattribute.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/jmstall/archive/2007/10/15/trivia-about-the-conditional-attribute.aspx"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-5716219127942039140?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/5716219127942039140/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=5716219127942039140' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/5716219127942039140'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/5716219127942039140'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/06/performance.html' title='Performance'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-4220038892287139485</id><published>2009-06-14T12:23:00.005+02:00</published><updated>2009-06-14T12:29:51.109+02:00</updated><title type='text'>The facts of life</title><content type='html'>&lt;div style="text-align: justify;"&gt;Recently I heard a very interesting song. It is called "The facts of life - Lazy Boy".&lt;br /&gt;&lt;/div&gt;This are the facts that impressed me most:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;3 people die every year, testing if a 9 volt battery works on their tongue&lt;/li&gt;&lt;li&gt;The 'Guinness Book Of Records' holds the record for being the most stolen book in public libraries&lt;/li&gt;&lt;li&gt;The worlds best known word is 'okay', the second most well-known word is 'Coca-Cola'&lt;/li&gt;&lt;li&gt;Charles Chaplin once won 3rd prize in a 'Charles Chaplin look-a-like contest'&lt;/li&gt;&lt;li&gt;Only one book has been printed in more copies than the Bible - the IKEA-catalogue&lt;/li&gt;&lt;li&gt;Did you know that originally a danish guy invented the burglar alarm? - unfortunately it got stolen&lt;/li&gt;&lt;/ul&gt;&lt;a href="http://www.sing365.com/music/lyric.nsf/Facts-Of-Life-lyrics-Lazyboy/1A92F8DD90529C4A48256F430010C416"&gt;Here&lt;/a&gt; you can find the whole song text in english... :-)&lt;br /&gt;&lt;br /&gt;And this is the video of the song (in italian):&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/aasRWKktOmk&amp;amp;hl=en&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/aasRWKktOmk&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-4220038892287139485?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/4220038892287139485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=4220038892287139485' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4220038892287139485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4220038892287139485'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/06/facts-of-life.html' title='The facts of life'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-5365386226724314010</id><published>2009-05-29T10:44:00.003+02:00</published><updated>2009-05-29T10:48:19.404+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><title type='text'>Just amazing</title><content type='html'>&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Today&lt;/span&gt; I &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;watched&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;the&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;demo&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;video&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;of&lt;/span&gt; Google &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;Waves&lt;/span&gt;. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;&lt;br /&gt;It&lt;/span&gt;'s just &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;amazing&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;what&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;these&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;guys built. Especially the translation "robot" that they show at the end of the demo :-)&lt;br /&gt;&lt;br /&gt;Here it is:&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/v_UyVmITiYQ&amp;rel=0&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en&amp;feature=player_embedded&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/v_UyVmITiYQ&amp;rel=0&amp;color1=0xb1b1b1&amp;color2=0xcfcfcf&amp;hl=en&amp;feature=player_embedded&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-5365386226724314010?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/5365386226724314010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=5365386226724314010' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/5365386226724314010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/5365386226724314010'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/05/just-amazing.html' title='Just amazing'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-4901612871608639757</id><published>2009-05-23T11:21:00.006+02:00</published><updated>2009-05-23T11:31:58.617+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>XSD element order</title><content type='html'>Recently I faced the problem that I had to create an XSD file to validate an XML file. The problem was that a requirement was that the elements could be in any order.&lt;br /&gt;First I had something like:&lt;br /&gt;&lt;br /&gt;&amp;lt;xs:sequence&amp;gt;&lt;br /&gt; &amp;lt;xs:element name="customer" /&amp;gt;&lt;br /&gt; &amp;lt;xs:element name="order" /&amp;gt;&lt;br /&gt;&amp;lt;/xs:sequence&amp;gt;&lt;br /&gt;&lt;br /&gt;which validates correctly:&lt;br /&gt;&lt;br /&gt;&amp;lt;root&amp;gt;&lt;br /&gt;  &amp;lt;customer /&amp;gt;&lt;br /&gt;  &amp;lt;customer /&amp;gt;&lt;br /&gt;  &amp;lt;customer /&amp;gt;&lt;br /&gt;  &amp;lt;order /&amp;gt;&lt;br /&gt;  &amp;lt;order /&amp;gt;&lt;br /&gt;  &amp;lt;order /&amp;gt;&lt;br /&gt;&amp;lt;/root&amp;gt;&lt;br /&gt;&lt;br /&gt;but I needed to validate something like:&lt;br /&gt;&lt;br /&gt;&amp;lt;root&amp;gt;&lt;br /&gt;  &amp;lt;order /&amp;gt;&lt;br /&gt;  &amp;lt;customer /&amp;gt;&lt;br /&gt;  &amp;lt;customer /&amp;gt;&lt;br /&gt;  &amp;lt;order /&amp;gt;&lt;br /&gt;  &amp;lt;customer /&amp;gt;&lt;br /&gt;  &amp;lt;order /&amp;gt;&lt;br /&gt;&amp;lt;/root&amp;gt;&lt;br /&gt;&lt;br /&gt;After some research I finally found the solution.&lt;br /&gt;instead of sequence You have to use choice with the min and max occurs attribute set:&lt;br /&gt;&lt;br /&gt;&amp;lt;xs:sequence&amp;gt;&lt;br /&gt;&amp;lt;/xs:sequence&amp;gt;&lt;br /&gt;&lt;br /&gt;is replaced with&lt;br /&gt;&lt;br /&gt;&amp;lt;xs:choice minOccurs="0" maxOccurs="unbounded"&amp;gt;&lt;br /&gt;&amp;lt;/xs:choice&amp;gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-4901612871608639757?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/4901612871608639757/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=4901612871608639757' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4901612871608639757'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4901612871608639757'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/05/xsd-element-order.html' title='XSD element order'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2791716189030820414</id><published>2009-04-21T17:58:00.005+02:00</published><updated>2009-04-21T18:16:23.009+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>LINQ Expression tree</title><content type='html'>Lately I had to implement my own LINQ to SQL "converter" which uses a custom mapping stored in the database. It is even not as difficult as I thought. You have "only" to recursively parse the expression tree and convert it to the correcsponding SQL instructions.&lt;br /&gt;The only thing I had some problems with were local variables or parameters.&lt;br /&gt;Consider the following code:&lt;br /&gt;&lt;pre class="prettyprint"&gt;int a = 3;&lt;br /&gt;Get&amp;lt;Person&amp;gt;(p =&amp;gt; p.Age == a);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;the class Person&lt;br /&gt;&lt;pre class="prettyprint"&gt;public class Person&lt;br /&gt;{&lt;br /&gt;    public int Age { get; set; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and the method&lt;br /&gt;&lt;pre class="prettyprint"&gt;public static void Get&amp;lt;T&amp;gt;(Expression&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt; e)&lt;br /&gt;{&lt;br /&gt;    MemberExpression member = (MemberExpression)((BinaryExpression)e.Body).Right;&lt;br /&gt;    ConstantExpression constant = (ConstantExpression)member.Expression;&lt;br /&gt;    Console.WriteLine(constant.Value.ToString());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;when analyzing the expression tree then You see that the right expression of the BinaryExpression is of type ConstantExpression. Normally ConstantExpression contain directly a value. But this is not the case here! The console writeline produces the following: "ConsoleApplication1.Program+&lt;&gt;c__DisplayClass0"&lt;br /&gt;The value of the constant expression is an anonymous object which is created on the fly. This object has a field which is named a and that field contains the value.&lt;br /&gt;Therefore I had to do the following:&lt;br /&gt;&lt;pre class="prettyprint"&gt;public static void Get&amp;lt;T&amp;gt;(Expression&amp;lt;Func&amp;lt;T, bool&amp;gt;&amp;gt; e)&lt;br /&gt;{&lt;br /&gt;    MemberExpression member = (MemberExpression)((BinaryExpression)e.Body).Right;&lt;br /&gt;    ConstantExpression constant = (ConstantExpression)member.Expression;&lt;br /&gt;    FieldInfo info = (FieldInfo)member.Member;&lt;br /&gt;    Console.WriteLine(info.GetValue(constant.Value).ToString());&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Instead of evaluating the expression which is associated to the MemberExpression.Expression I used the Member and casted it to a FieldInfo. Then I called the GetValue method passing it the value of the ConstantExpression which is basically the object. In this way I finally got the correct value of a.&lt;br /&gt;The same works also for method parameters. Consider this code:&lt;br /&gt;&lt;pre class="prettyprint"&gt;public static void FromMethod(int a)&lt;br /&gt;{&lt;br /&gt;    Get&amp;lt;Person&amp;gt;(p =&amp;gt; p.Age == a);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;there we have exactly the same problem and it can be resolved in the way described above.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2791716189030820414?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2791716189030820414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2791716189030820414' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2791716189030820414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2791716189030820414'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/04/linq-expression-tree.html' title='LINQ Expression tree'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2660515146521139181</id><published>2009-03-25T17:33:00.004+01:00</published><updated>2009-03-31T16:40:31.112+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>Bulk insert of data</title><content type='html'>&lt;div style="text-align: justify;"&gt;Recently I faced the problem of inserting a big amount of data into the database. The point is that multiple tables are affected which are connected with foreign keys. After some research I found &lt;a href="http://msdn.microsoft.com/en-us/library/ms186918%28SQL.90%29.aspx"&gt;&lt;/a&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms186918%28SQL.90%29.aspx"&gt;OpenXML&lt;/a&gt; as one possibility. You create a stored procedure where you read your XML string into an "XmlDocument" which you can then query by using &lt;a href="http://en.wikipedia.org/wiki/XPath"&gt;XPath&lt;/a&gt; and inserting, updating or deleting the tables occordingly.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The other possibility I found is &lt;a href="http://msdn.microsoft.com/en-us/library/ms171779.aspx"&gt;SQLXML&lt;/a&gt; which is now available in version 4.1. It is delivered with SQL Server but not with the Express version. If you need it you can download it from &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=228DE03F-3B5A-428A-923F-58A033D316E1&amp;amp;displaylang=en"&gt;here&lt;/a&gt;. SQLXML allows you to bulk insert data from an XML file by using a so called annotated XSD schema where the mapping is defined. It is not very difficult to define the schema, only recursion and special cases are a little bit difficult to handle. I was not able to make recursion work with identity values coming from the database. Anyway; I did some performance tests where I had a structure like:&lt;br /&gt;Table A&lt;br /&gt;Table B has a foreign key to Table A&lt;br /&gt;Table C has a foreign key to Table B&lt;br /&gt;which corresponds to the following XML structure:&lt;br /&gt;&amp;lt;root&amp;gt;&lt;br /&gt; &amp;lt;a&amp;gt;&lt;br /&gt;   &amp;lt;b&amp;gt;&lt;br /&gt;     &amp;lt;c&amp;gt;&amp;lt;/c&amp;gt;&lt;br /&gt;   &amp;lt;/b&amp;gt;&lt;br /&gt; &amp;lt;/a&amp;gt;&lt;br /&gt;&amp;lt;/root&amp;gt;&lt;br /&gt;&lt;br /&gt;I created an XML file that contained 100 A's; every A contained 100 B's and every B contained 100 C's. This gives a total of 100 A's, 10.000 B's and 1.000.000 C's. To insert all them and updating the foreign keys it took 84 seconds. This is quite fast for such an amount of data. I think that this is the fastest way to bulk insert data into SQL Server (if I'm wrong You are welcome to coment on this).&lt;br /&gt;If you want to use it with .Net add a reference to "Microsoft SQL Server Bulk Upload" or something like that.&lt;br /&gt;I don't remember the exact name but as soon as I find the link of the code sample I will post it here.&lt;br /&gt;&lt;br /&gt;The problem is that SQLXML cannot be used for updates. There exist so called updategrams or diffgrams but I didn't try them.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2660515146521139181?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2660515146521139181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2660515146521139181' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2660515146521139181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2660515146521139181'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/03/bulk-insert-of-data.html' title='Bulk insert of data'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-3975568095533613180</id><published>2009-03-25T17:19:00.004+01:00</published><updated>2009-03-25T17:33:12.333+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><title type='text'>Very Simple Notes Application</title><content type='html'>&lt;div style="text-align: justify;"&gt;My girlfriend asked me look for a small program wher she can add notes and delete them if necessary. I serached the internet and there are a lot of programs out there to do this, but they are all very complex and offer a huge amount of feautres that she does not need. Since I'm a programmer I decided to write one :-)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;As the title says it is a really simple program. Here a screenshot of it:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/simpleNote.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 436px; height: 363px;" src="http://manfred.ramoser.googlepages.com/simpleNote.png" alt="" border="0" /&gt;&lt;/a&gt;and this is how it looks with some notes:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/simpleNote1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 436px; height: 363px;" src="http://manfred.ramoser.googlepages.com/simpleNote1.png" alt="" border="0" /&gt;&lt;/a&gt;Obviously by clicking the trash the note is deleted. All the notes are saved in a simple XML file in the isolated storage of the user. This means that you can run the application from a readonly storage (like a CD) and it saves all Your notes in your user profiles folder.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;If someone is interested in this very simple tool You can get it from &lt;a href="http://manfred.ramoser.googlepages.com/SimpleNote.exe"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-3975568095533613180?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/3975568095533613180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=3975568095533613180' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3975568095533613180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3975568095533613180'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/03/very-simple-notes-application.html' title='Very Simple Notes Application'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-4175515228383703553</id><published>2009-01-29T17:44:00.002+01:00</published><updated>2009-01-29T17:53:59.011+01:00</updated><title type='text'>No standard mail client</title><content type='html'>Today I encountered a nasty problem. I clicked on an e-mail address on a web page and instead of opening Thunderbird with a new mail message I got the following error "Der Vorgang kann nicht ausgeführt werden weil der Standard-Mailclient nicht richtig installiert ist.". This means something like "The operation can not be performed because the standard mail client was not correctly installed.".&lt;br /&gt;I told Thunderbird to ckeck if it is the standard mail client under Extras -&gt; Settings -&gt; General -&gt; Standard mail client (I don't know if that is correct because I have a german version); it told me that it is the standard mail client.&lt;br /&gt;&lt;br /&gt;Finally to make it work I had to go in the Internet Explorer (7) to Extras -&gt; Internet options -&gt; Programs and there I selected Thunderbird as standard mail client.&lt;br /&gt;&lt;br /&gt;Strange thing; but sometimes things stop to work without any obvious reasons :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-4175515228383703553?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/4175515228383703553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=4175515228383703553' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4175515228383703553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4175515228383703553'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/01/no-standard-mail-client.html' title='No standard mail client'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-1325720324716856319</id><published>2009-01-21T20:41:00.004+01:00</published><updated>2009-01-22T21:13:56.703+01:00</updated><title type='text'>Microsoft Certification</title><content type='html'>&lt;div style="text-align: justify;"&gt;Today I passed the microsoft exam &lt;a href="http://www.microsoft.com/learning/en/us/exams/70-536.aspx"&gt;70536 &lt;span id="labelExamTitleName" class="DetailPagesBlackColorSubHeading"&gt;Microsoft .NET Framework - Application Development Foundation.&lt;/span&gt;&lt;/a&gt; I found it very interesting to prepare myself for this exam because despite that I program every day at work there were a lot of things that I simply didn't know that they exist. Other things I never understood completely and this exam helped me to find out how and why it works in this way. The exam itself was not very easy because the questions are very detailed and sometimes you simply have to have used some classes in order to know if a parameter is passed through the constructor or set with a property. The most difficult are the questions wher you have a list of steps and you have to bring them in the correct order; but not all steps may be needed. I find these kind of questions especially difficult because sometimes there is not only one way to accomplish the specified target. Anyway I am happy that I passed the exam and that now I can prepare myself for the next exam... a never ending story :-)&lt;br /&gt;&lt;br /&gt;[Update]&lt;br /&gt;Now I got access to the MCP website from where I also got the logo which I proudly put on the right  menu bar :-)&lt;br /&gt;&lt;/div&gt;&lt;a href="http://www.microsoft.com/learning/en/us/exams/70-536.aspx"&gt;&lt;span id="labelExamTitleName" class="DetailPagesBlackColorSubHeading"&gt;&lt;/span&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-1325720324716856319?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/1325720324716856319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=1325720324716856319' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/1325720324716856319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/1325720324716856319'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/01/microsoft-certification.html' title='Microsoft Certification'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2408637173029416406</id><published>2009-01-07T18:37:00.003+01:00</published><updated>2009-01-07T18:44:02.987+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Updating App.config</title><content type='html'>&lt;div style="text-align: justify;"&gt;Today I faced the problem to update the App.config. There exist several solutions out there but I was not able to find a simple one. Therefore I decided to try out the new Linq to XML feature of .NET 3.5 and wrote the following method which updates the value of a specific key in the App.config file:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;public static void UpdateAppConfig(string key, object value)&lt;br /&gt;{&lt;br /&gt;  if (key == null)&lt;br /&gt;      throw new ArgumentNullException("key");&lt;br /&gt;&lt;br /&gt;  if (value == null)&lt;br /&gt;      throw new ArgumentNullException("value");&lt;br /&gt;&lt;br /&gt;  XDocument doc = XDocument.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);&lt;br /&gt;  var result = (from appSetting in doc.Descendants("appSettings").Descendants("add")&lt;br /&gt;                where appSetting.Attribute("key").Value.Equals(key)&lt;br /&gt;                select appSetting).FirstOrDefault();&lt;br /&gt;&lt;br /&gt;  if (result != null)&lt;br /&gt;  {&lt;br /&gt;      result.Attribute("value").SetValue(value);&lt;br /&gt;      doc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);&lt;br /&gt;      doc = null;&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;      Console.WriteLine("The application setting with key '{0}' was not found!", key);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2408637173029416406?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2408637173029416406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2408637173029416406' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2408637173029416406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2408637173029416406'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/01/updating-appconfig.html' title='Updating App.config'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2663413551604228439</id><published>2009-01-07T17:45:00.003+01:00</published><updated>2009-01-07T18:36:16.596+01:00</updated><title type='text'>Blog statistics 2008</title><content type='html'>&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;As&lt;/span&gt; I &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;saw&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;it&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;is&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;common&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;to&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;post&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;some&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;statistics&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;about&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;his&lt;/span&gt; blog. So also I will &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;follow&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;this&lt;/span&gt; "&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;trend&lt;/span&gt;" :-)&lt;br /&gt;&lt;br /&gt;First &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;of&lt;/span&gt; all &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;here&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;the&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;graph&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;of&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;accesse&lt;/span&gt; per &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;day&lt;/span&gt;. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;Ultimately&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;there&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;is&lt;/span&gt; an &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;average&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;of&lt;/span&gt; 25 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;visits&lt;/span&gt; per &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;day&lt;/span&gt;. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;The&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;most&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;visits&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;were&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;on&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;July&lt;/span&gt; 1. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;There&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;were&lt;/span&gt; 57 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;visits&lt;/span&gt; :-)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/visitors_2008.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 698px; height: 121px;" src="http://manfred.ramoser.googlepages.com/visitors_2008.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;As&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;you&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;can&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;see&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;here&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;most&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;people&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;get&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;directed&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;by&lt;/span&gt; a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;search&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;engine&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_49"&gt;to&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;my&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;page&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/traffic_2008.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 780px; height: 138px;" src="http://manfred.ramoser.googlepages.com/traffic_2008.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;The&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_53"&gt;most&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_54"&gt;visitors&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_55"&gt;access&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_56"&gt;from&lt;/span&gt; London &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_57"&gt;my&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_58"&gt;page&lt;/span&gt;, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_59"&gt;but&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_60"&gt;there&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_61"&gt;are&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_62"&gt;visitors&lt;/span&gt; all &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_63"&gt;over&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_64"&gt;the&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_65"&gt;world&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/map_2008.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 789px; height: 410px;" src="http://manfred.ramoser.googlepages.com/map_2008.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/returning_visitors_2008.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 870px; height: 250px;" src="http://manfred.ramoser.googlepages.com/returning_visitors_2008.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_66"&gt;wish&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_67"&gt;everybody&lt;/span&gt; a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_68"&gt;happy&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_69"&gt;and&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_70"&gt;good&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_71"&gt;new&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_72"&gt;year&lt;/span&gt; 2009 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_73"&gt;and&lt;/span&gt; I &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_74"&gt;would&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_75"&gt;be&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_76"&gt;happy&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_77"&gt;if&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_78"&gt;you&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_79"&gt;continue&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_80"&gt;to&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_81"&gt;visit&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_82"&gt;my&lt;/span&gt; blog ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2663413551604228439?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2663413551604228439/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2663413551604228439' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2663413551604228439'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2663413551604228439'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2009/01/blog-statistics-2008.html' title='Blog statistics 2008'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-5217849182684504877</id><published>2008-12-14T15:45:00.002+01:00</published><updated>2008-12-14T16:06:13.885+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Localizing .NET applications</title><content type='html'>&lt;div style="text-align: justify;"&gt;Most applications nowadays have to be localized in order to provide user interfaces in the language of the user who uses the application. The .NET framework offers a very handy mechanism to provide localization for your apps. It uses so called resource files (.resx) to store keys and the corresponding translated texts or images. If you want to know more on how to work with this translation mechanism take a look at &lt;a href="http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=211"&gt;this post&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The main problem with these files is to keep them in sync (for example when adding new strings) and to give translators an easy tool to make translation without requiring them to  have visual studio installed on their computers.&lt;br /&gt;I found a tool called "ResEx ... the composite, translation friendly .NET Resource editor" which can be found &lt;a href="http://www.papadi.gr/resex.aspx"&gt;here&lt;/a&gt; that meets exactly this requriements. It provides a nice spreadsheet interface which makes it also for non programmers easy to translate the resources in the files. It is also possible to group resources together by using an underscore e.g. Menu_Home, Menu_Customers; they will all be shown under the tree node "Menu" which makes it easier to understand where the translations are used. Even adding and deleting localization languages is very easy.&lt;br /&gt;The only thing which is missing is to have an automatic translation by using one of the several online translators available nowadays. I will suggest it on the forum and maybe this feature will be available in a future release.&lt;br /&gt;&lt;br /&gt;Another very useful tool when working with resource files is the &lt;a href="http://www.codeplex.com/ResourceRefactoring"&gt;Resoucre Refactoring Tool&lt;/a&gt; on CodePlex. It helps you by localize strings in your source code by putting the string into the resource file and replacing the corresponding call in order to get a translated string.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-5217849182684504877?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/5217849182684504877/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=5217849182684504877' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/5217849182684504877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/5217849182684504877'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/12/localizing-net-applications.html' title='Localizing .NET applications'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-3171951551283661565</id><published>2008-12-14T14:26:00.004+01:00</published><updated>2008-12-14T14:59:16.977+01:00</updated><title type='text'>Generating script for SQL Server database</title><content type='html'>&lt;div style="text-align: justify;"&gt;Recently I had to deploy a project which used a Microsoft SQL Server database. During the deployment process all the tables and some predefined data should be created in the database of the machine on which the application is installed. I needed a simple .sql file which contains SQL instructions to create the schema and to insert the data. I thought that this would not be a big deal because SQL Server Management Studio has many tools and functionalities and for sure also one to do this since it is an essential part of software deployment. I used the export Wizard and everything worked well except that with the Wizard it is only possible to export the schema. I was very surprised that it is not possible to export the schema and the data.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;After some research on the internet I found several commercial tools which are able to export also the data but I did not want to purchase such a tool only to export the data.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I found that there is an "API" for the &lt;a href="http://msdn.microsoft.com/en-us/library/ms162169.aspx"&gt;SQL Server which is called SQL Server Management Objects (SMO) and SQL Server Replication Objects (RMO)&lt;/a&gt;. These two "API's" can be used to get information from an SQL Server such as all the databases, all the tables in a database and all other information related to an SQL Server. I played a bit with them and there exists a method for each server object (such as databases, tables,...) which is called Script(). This method returns a StringCollection which can be used to re-create the SQL object. It is worth to give a look if you have to create, update or delete SQL objects from within code.&lt;br /&gt;I tried to build a tool which is able to export a whole database, all its objects (function, triggers,...) and the data to a single sql file. I faced several problems. First it is important in which order the tables and constraints are created because otherwise the script would not run successfully. Second I had to generate insert statements for the data which has to consider all datatypes supported by SQL Server.&lt;br /&gt;In some way I would have been able to solve these two issues but then I found the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=56E5B1C5-BF17-42E0-A410-371A838E570A&amp;amp;displaylang=en"&gt;Microsoft SQL Server Database Publishing Wizard 1.1&lt;/a&gt;. This tool by Microsoft does exactly what I need. It exports one or more databases with their schema, objects and the data. If you have a similar issue I suggest you to use this one since it is free and worked fine for me :-)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.codeplex.com/sqlhost/Wiki/View.aspx?title=Database%20Publishing%20Wizard"&gt;Here&lt;/a&gt; you can find the official home page of the publishing wizard tool on CodePlex.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-3171951551283661565?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/3171951551283661565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=3171951551283661565' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3171951551283661565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3171951551283661565'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/12/generating-script-for-sql-server.html' title='Generating script for SQL Server database'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2506708039152458967</id><published>2008-12-01T19:34:00.004+01:00</published><updated>2008-12-01T20:09:42.858+01:00</updated><title type='text'>Show Collection of strings in GridView</title><content type='html'>&lt;div style="text-align: justify;"&gt;Today I faced the following problem; I had a collection of strings which I wanted to show in a GridView. I tried to use the collection as datasource, but nothing was displayed. A quick and simple solution to this problem is the following:&lt;br /&gt;&lt;/div&gt;- First you add a template column to the grid view&lt;br /&gt;&lt;div style="text-align: justify;"&gt;- In the template for the item you create a Literal control&lt;br /&gt;&lt;/div&gt;- Then the Text property of the Literal is set to DataItem of the Container which is evaluated when databinding occurs&lt;br /&gt;&lt;br /&gt;This can be accomplished with the following code:&lt;br /&gt;&lt;pre&gt;&amp;lt;asp:gridview id="GridView1" runat="server" autogeneratecolumns="False" onrowdeleting="GridView1_RowDeleting"&amp;gt;&lt;br /&gt;&amp;lt;columns&amp;gt;&lt;br /&gt; &amp;lt;asp:templatefield headertext="column"&amp;gt;&lt;br /&gt;            &amp;lt;itemtemplate&amp;gt;&lt;br /&gt;             &amp;lt;asp:literal runat="server" id="customerNames" text="&amp;lt;%# Container.DataItem %&gt;"&amp;gt;&amp;lt;/asp:literal&amp;gt;&lt;br /&gt;            &amp;lt;/itemtemplate&amp;gt;&lt;br /&gt;           &amp;lt;/asp:templatefield&amp;gt;&lt;br /&gt;           &amp;lt;asp:commandfield showdeletebutton="True"&amp;gt;&lt;br /&gt;        &amp;lt;/asp:commandfield&amp;gt;&lt;br /&gt;   &amp;lt;/columns&amp;gt;&lt;br /&gt;&amp;lt;/asp:gridview&amp;gt;&lt;/pre&gt;&lt;br /&gt;This code sets a string collection as datasource and binds it to the gridview:&lt;br /&gt;&lt;pre class="prettyprint"&gt;List&amp;lt;string&amp;gt; list = new List&amp;lt;string&amp;gt;();&lt;br /&gt;list.Add("Customer1");&lt;br /&gt;list.Add("Customer2");&lt;br /&gt;list.Add("Customer3");&lt;br /&gt;list.Add("Customer4");&lt;br /&gt;list.Add("Customer5");&lt;br /&gt;list.Add("Customer6");&lt;br /&gt;&lt;br /&gt;this.GridView1.DataSource = list;&lt;br /&gt;this.GridView1.DataBind();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;But now is the question: how con you retrieve the value for example in the RowDeleting event. As accustomed to windows forms I tried:&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;this.GridView1.Rows[e.RowIndex].Cells[0].Text;&lt;/pre&gt;&lt;br /&gt;but that did not work. To get the correct text I had to use:&lt;br /&gt;&lt;pre class="prettyprint"&gt;((Literal)this.GridView1.Rows[e.RowIndex].Cells[0].Controls[1]).Text;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Alltogether the cell contains 3 controls. The other two are LiteralControls with the Text '\r\n        ' and the second one is the Literal control which holds the text.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2506708039152458967?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2506708039152458967/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2506708039152458967' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2506708039152458967'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2506708039152458967'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/12/show-collection-of-strings-in-gridview.html' title='Show Collection of strings in GridView'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2681832337264311197</id><published>2008-11-25T17:36:00.007+01:00</published><updated>2008-11-29T13:20:08.309+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><title type='text'>INSERT if new and UPDATE otherwise</title><content type='html'>&lt;div style="text-align: justify;"&gt;Recently I faced the following problem. I had to insert a big number of records into a PostgreSQL database. I have created a string which contains the various insert statements like below. The primary key is defined on the columns a,b.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;INSERT INTO tablename (a,b,c) VALUES (1,2,'abc');&lt;br /&gt;INSERT INTO tablename (a,b,c) VALUES (2,2,'def');&lt;br /&gt;INSERT INTO tablename (a,b,c) VALUES (2,2,'ghi'); --generates an error!!&lt;br /&gt;INSERT INTO tablename (a,b,c) VALUES (3,2,'ghi');&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This worked fine until I encountered a duplicate primary key violation. The main problem with this was that after the error, the transaction was aborted and rolled back.  So no record was inserted. I wanted instead that if such an error occurs, the existing record gets simply updated with the new values and if no record exists, it should be inserted. I searched the internet and there where different proposals but none of them really convinced me. I then came up with the following function:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;&lt;br /&gt;CREATE OR REPLACE FUNCTION insert_update_record(a_in int, b_in int, c_in character varying)&lt;br /&gt;RETURNS void AS&lt;br /&gt;$BODY$&lt;br /&gt;BEGIN&lt;br /&gt;          -- try to insert the record&lt;br /&gt;          BEGIN&lt;br /&gt;              INSERT INTO tablename (a,b,c) VALUES (a_in, b_in, c_in);&lt;br /&gt;              RETURN;&lt;br /&gt;          EXCEPTION WHEN unique_violation THEN&lt;br /&gt;              -- if there is a duplicate key exception&lt;br /&gt;              -- update the record&lt;br /&gt;              UPDATE tablename SET c = c_in WHERE a = a_in AND b = b_in;&lt;br /&gt;          END;&lt;br /&gt;END;&lt;br /&gt;$BODY$&lt;br /&gt;LANGUAGE 'plpgsql' VOLATILE&lt;br /&gt;COST 100;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This function simply tries to insert the new record into the table and if there is a duplicate key exception it will update the record. The previous insert statements would then be converted to:&lt;br /&gt;&lt;/div&gt;&lt;pre&gt;&lt;br /&gt;SELECT insert_update_record(1,2,'abc');&lt;br /&gt;SELECT insert_update_record(2,2,'def');&lt;br /&gt;SELECT insert_update_record(2,2,'ghi'); --generates an error but does not abort the transaction&lt;br /&gt;SELECT insert_update_record(3,2,'ghi');&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;I did not make any performance tests, but I believe that this function is not much slower than the INSERT statements if there are not many duplicates; because it simply makes an insert and returns and only if there is an exception it does some additional work. Since this function is precompiled it may be that it is even faster than the INSERT statement. Anyway the function can help you solve the insert/update problem.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Of course you have to adjust the function according to your needs, but if you have some experience with programming it shouldn't be too difficult ;-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;UPDATE:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Based on the suggestion of Peter I made up a new function which is pratically an implementation for PostgreSQL of his pseudo SQL statements:&lt;br /&gt;&lt;pre&gt;UPDATE sample&lt;br /&gt;SET testno = 1;&lt;br /&gt;WHERE test = 'PL/SQL';&lt;br /&gt;IF SQL%ROWCOUNT ==0&lt;br /&gt;THEN&lt;br /&gt;/* Insert Statement */&lt;br /&gt;&lt;br /&gt;END IF;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I have created then a table 'test' with the columns 'id' (pk), 'val1' and 'val2'. Then I converted the pseudo SQL into:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE OR REPLACE FUNCTION update_insert(id_in integer, val1_in integer, val2_in integer)&lt;br /&gt;RETURNS void AS&lt;br /&gt;$BODY$&lt;br /&gt;DECLARE&lt;br /&gt;count int;&lt;br /&gt;BEGIN&lt;br /&gt;update test set val1 = val1_in, val2 = val2_in where id = id_in;&lt;br /&gt;    GET DIAGNOSTICS count = ROW_COUNT;&lt;br /&gt;&lt;br /&gt;    IF count = 0 THEN&lt;br /&gt;     INSERT INTO test (id, val1, val2) VALUES (id_in, val1_in, val2_in);&lt;br /&gt;END IF;&lt;br /&gt;END;&lt;br /&gt;$BODY$&lt;br /&gt;LANGUAGE 'plpgsql' VOLATILE&lt;br /&gt;COST 100;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and provided also the function for this table with the exception handling:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE OR REPLACE FUNCTION insert_update(id_in integer, val1_in integer, val2_in integer)&lt;br /&gt;RETURNS void AS&lt;br /&gt;$BODY$&lt;br /&gt;BEGIN&lt;br /&gt;            -- try to insert the record&lt;br /&gt;            BEGIN&lt;br /&gt;                INSERT INTO test (id,val1,val2) VALUES (id_in, val1_in, val2_in);&lt;br /&gt;                RETURN;&lt;br /&gt;            EXCEPTION WHEN unique_violation THEN&lt;br /&gt;                -- if there is a duplicate key exception&lt;br /&gt;                -- update the record&lt;br /&gt;                UPDATE test SET val1 = val1_in, val2 = val2_in WHERE id = id_in;&lt;br /&gt;            END;&lt;br /&gt;END;&lt;br /&gt;$BODY$&lt;br /&gt;LANGUAGE 'plpgsql' VOLATILE&lt;br /&gt;COST 100;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then I created with a small application the SQL statements that call these functions and I created them with differenct percentage of duplicates:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SELECT insert_update(1,101,-99);&lt;br /&gt;and&lt;br /&gt;SELECT update_insert(1,101,-99);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here are the results of my performance measures:&lt;br /&gt;1 000 statements&lt;br /&gt;tried to insert every id twice -&gt; 500 records in DB&lt;br /&gt;update_insert: 250ms&lt;br /&gt;insert_update: 250ms&lt;br /&gt;&lt;br /&gt;100 000 statements&lt;br /&gt;tried to insert every id twice -&gt; 50 000 records in DB&lt;br /&gt;update_insert: 37281ms&lt;br /&gt;insert_update: 45125ms&lt;br /&gt;&lt;br /&gt;100 000&lt;br /&gt;every 10th record was already present -&gt; 90 000 records in DB&lt;br /&gt;update_insert: 63875ms&lt;br /&gt;insert_update: 61500ms&lt;br /&gt;&lt;br /&gt;10 000&lt;br /&gt;all ids were the same -&gt; 1 record in DB&lt;br /&gt;update_insert 10016ms&lt;br /&gt;insert_update 18703ms&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;I did the tests on my laptop; I know that they may not be precise because of running services in the background, but at least they give an intuition.&lt;br /&gt;&lt;/div&gt;The result of my test:&lt;br /&gt;- High number of duplicates -&gt; the update/insert function is much faster&lt;br /&gt;- Low number of duplicates -&gt; the two functions are almost equally fast&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;I was surprised that there is not more difference between these two functions. I expected that the function with the exception would be much slower than the other one. I would suggest to use the update/insert function as proposed by Peter because exceptions should only be used in exceptional situations and avoided when possible.&lt;br /&gt;Thanks Peter for the proposal...&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2681832337264311197?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2681832337264311197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2681832337264311197' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2681832337264311197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2681832337264311197'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/11/insert-if-new-and-update-otherwise.html' title='INSERT if new and UPDATE otherwise'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-6010336520723443310</id><published>2008-10-18T11:45:00.010+02:00</published><updated>2008-11-25T18:09:39.639+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Extension Methods in C#</title><content type='html'>&lt;div style="text-align: justify;"&gt;There are some new features in C# 3 which are introduced to make LINQ possible.&lt;br /&gt;One of them are extension methods which I wanted to try out. Extension methods are static methods which can be applied to any object type which is specified as "special parameter". For example if you want to extend the type string with the method "Greet" you write something like this:&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;public static void Greet(this String s)&lt;br /&gt;{&lt;br /&gt;Console.WriteLine("Hello " +  s);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then you can call it like:&lt;pre class="prettyprint"&gt;string name = "Tom";&lt;br /&gt;name.Greet();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This will produce the following on the console: "Hello Tom"&lt;br /&gt;&lt;br /&gt;I played a bit with this extension mehtods and came up with the following extensions for object which I believe can be helpful.&lt;br /&gt;Assume the following object:&lt;pre class="prettyprint"&gt;Customer testCustomer = new Customer() { Name = "John", Age = 35, LastName = "Smith" };&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PrintConsole()&lt;/span&gt; -&gt; prints the string representation of an object to the console&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code:&lt;/span&gt;&lt;pre class="prettyprint"&gt;testCustomer.PrintConsole();&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Produces:&lt;/span&gt;&lt;br /&gt;"ExtensionMethodTest.Customer"&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PrintMessageBox() &lt;/span&gt;-&gt; shows the string representation of an object in a message box&lt;br /&gt;Code:&lt;pre class="prettyprint"&gt;testCustomer.PrintMessageBox();&lt;/pre&gt;&lt;br /&gt;Produces:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/print.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://manfred.ramoser.googlepages.com/print.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PrintPropertiesConsole()&lt;/span&gt; -&gt; Prints all public non inherited properties and their values of the object to the console&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code:&lt;/span&gt;&lt;pre class="prettyprint"&gt;testCustomer.PrintPropertiesConsole();&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Produces:&lt;/span&gt;&lt;br /&gt;Properties of 'ExtensionMethodTest.Customer'&lt;br /&gt;Name: John&lt;br /&gt;LastName: Smith&lt;br /&gt;Age: 35&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;PrintPropertiesMessageBox() &lt;/span&gt;-&gt; Shows all public non inherited properties and their values of the object in a message box&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code:&lt;/span&gt;&lt;pre class="prettyprint"&gt;testCustomer.PrintPropertiesMessageBox();&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Produces&lt;/span&gt;:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/print_properties.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://manfred.ramoser.googlepages.com/print_properties.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;string ToXml()&lt;/span&gt; -&gt; Serializes the object to XML and returns the XML string&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code:&lt;/span&gt;&lt;pre class="prettyprint"&gt;testCustomer.ToXml();&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Produces:&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;&lt;customer xsi="http://www.w3.org/2001/XMLSchema-instance" xsd="http://www.w3.org/2001/XMLSchema"&gt;&lt;br /&gt;&lt;name&gt;John&lt;/name&gt;&lt;br /&gt;&lt;lastname&gt;Smith&lt;/lastname&gt;&lt;br /&gt;&lt;age&gt;35&lt;/age&gt;&lt;br /&gt;&lt;/customer&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;ToXml(Stream stream)&lt;/span&gt; -&gt; Serializes the object to XML and writes it to the stream&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code:&lt;/span&gt;&lt;pre class="prettyprint"&gt;testCustomer.ToXml(myStream);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;ToXml(string fileName) &lt;/span&gt;-&gt; Serializes the object to XML and writes the XML string to the file specified.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code:&lt;/span&gt;&lt;pre class="prettyprint"&gt;testCustomer.ToXml("c://test.xml);&lt;/pre&gt;&lt;br /&gt;If you are interested in my project you can download it from &lt;a href="http://manfred.ramoser.googlepages.com/ExtensionMethodsTest.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;Or you can simply download the Extensions.dll from &lt;a href="http://manfred.ramoser.googlepages.com/Extensions.dll"&gt;here&lt;/a&gt; and import it into your project.&lt;br /&gt;&lt;br /&gt;All extension methods are in the namespace System. I know that this is not the way how to do it but so you don't have to add a using directive because System is by default present.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-6010336520723443310?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/6010336520723443310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=6010336520723443310' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/6010336520723443310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/6010336520723443310'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/10/extension-methods-in-c.html' title='Extension Methods in C#'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2843673245829564013</id><published>2008-10-18T10:59:00.005+02:00</published><updated>2008-10-18T11:41:08.637+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><title type='text'>XPath</title><content type='html'>&lt;div style="text-align: justify;"&gt;For them of you which do not know what &lt;a href="http://en.wikipedia.org/wiki/Xpath"&gt;XPath&lt;/a&gt; is; it is a very powerful query language for XML data. But it can also more than querying data; it can also compute values, find the max or min of an attribute and even produce a different output format. For example it is possible to write HTML code with XML data. C# provides different classes to execute XPath queries on XML files which are located in the "System.Xml.Xpath" namespace.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The problem, at least for me, is that I do not use XPath so often as that I always remember the sometimes tricky XPath-Syntax. Here I found it very helpful to have a graphical tool where I can type in my query and see the results of the query. I found such a tool which is freeware; &lt;a href="http://pgfearo.googlepages.com/home"&gt;Sketch Path&lt;/a&gt;. It is a very powerful tool which not only shows you the result of a query but also assists you when writing a query by providing common operations and selectors.&lt;br /&gt;&lt;br /&gt;I can only encourage you to try XPath when working with XML data because it really makes it easier to get the data you want. Especially if you use XML files instead of a database. XPath can be seen as the SQL for XML files.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Here there is a screenshot of Sketch Path where I searched in a list of customers for all customers which are older than 50. The query is quite simple:&lt;br /&gt;//Customer[Age&gt;50]&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/sketchpath.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://manfred.ramoser.googlepages.com/sketchpath.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Another nice thing which is very helpful is that if you select a node then it shows you the path to this node which can help you creating your query:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/sketchpath_nodepath.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://manfred.ramoser.googlepages.com/sketchpath_nodepath.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.w3schools.com/XPath/xpath_syntax.asp"&gt;&lt;/a&gt;&lt;a href="http://www.w3schools.com/XPath/xpath_syntax.asp"&gt;Here&lt;/a&gt; you can find a tutorial on XPath Syntax.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2843673245829564013?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2843673245829564013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2843673245829564013' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2843673245829564013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2843673245829564013'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/10/xpath.html' title='XPath'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-4418359773037695990</id><published>2008-09-05T16:32:00.005+02:00</published><updated>2008-09-05T16:50:03.500+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>TreeView node font problem</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/tree_problem_wrong.jpg"&gt;&lt;/a&gt;&lt;div style="text-align: justify;"&gt;Recently I encountered the following problem. I needed to set the font style of some nodes in a treeview at runtime to bold; but after setting the NodeFont property of the node the font changed correctly, but the text of the node was cut off.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;This screenshot shows the problem:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/tree_problem_wrong.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://manfred.ramoser.googlepages.com/tree_problem_wrong.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The solution to the problem is to add an empty string to the Text property after setting the NodeFont property:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;this.treeView1.SelectedNode.NodeFont = new Font(this.treeView1.Font, FontStyle.Bold);&lt;br /&gt;this.treeView1.SelectedNode.Text += string.Empty;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The problem is also known at Microsoft and I found this workaround &lt;a href="http://support.microsoft.com/?scid=kb%3Ben-us%3B937215&amp;amp;x=8&amp;amp;y=13"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This screenshot shows the correct text:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/tree_problem_correct.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://manfred.ramoser.googlepages.com/tree_problem_correct.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-4418359773037695990?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/4418359773037695990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=4418359773037695990' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4418359773037695990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4418359773037695990'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/09/treeview-node-font-problem.html' title='TreeView node font problem'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-7919930924401438858</id><published>2008-06-16T16:26:00.006+02:00</published><updated>2008-12-18T17:45:40.347+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Enhanced combobox with readonly and working value member</title><content type='html'>&lt;div style="text-align: justify;"&gt;As I had several problems with the standard combo box of the .Net 2.0 Framework such as the missing read only property or the not working value member property (if not using a datasource), I decided to write my own improved combo box. To change the default combobox to my needs I overwrote the OnPaint() mehtod and provided some additional methods.&lt;br /&gt;&lt;br /&gt;With the enhanced combo box you can finally specify a value member without having to use a datasource as you can see in the code below:&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;Customer customer1 = new Customer();&lt;br /&gt;customer1.FirstName = "John";&lt;br /&gt;customer1.ID = 1;&lt;br /&gt;customer1.LastName = "Smith";&lt;br /&gt;&lt;br /&gt;Customer customer2 = new Customer();&lt;br /&gt;customer2.FirstName = "Marco";&lt;br /&gt;customer2.ID = 2;&lt;br /&gt;customer2.LastName = "Polo";&lt;br /&gt;&lt;br /&gt;this.cmbTest.Items.Add(customer1);&lt;br /&gt;this.cmbTest.Items.Add(customer2);&lt;br /&gt;&lt;br /&gt;this.cmbTest.DisplayMember = "FirstName";&lt;br /&gt;this.cmbTest.ValueMember = "ID";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Or you can use a datasource:&lt;br /&gt;&lt;pre class="prettyprint"&gt;Customer customer1 = new Customer();&lt;br /&gt;customer1.FirstName = "John";&lt;br /&gt;customer1.ID = 1;&lt;br /&gt;customer1.LastName = "Smith";&lt;br /&gt;&lt;br /&gt;Customer customer2 = new Customer();&lt;br /&gt;customer2.FirstName = "Marco";&lt;br /&gt;customer2.ID = 2;&lt;br /&gt;customer2.LastName = "Polo";&lt;br /&gt;&lt;br /&gt;Customer customer3 = new Customer();&lt;br /&gt;customer3.FirstName = "Tom";&lt;br /&gt;customer3.ID = 3;&lt;br /&gt;customer3.LastName = "Hanks";&lt;br /&gt;&lt;br /&gt;List&lt;customer&gt; customers = new List&lt;customer&gt;();&lt;br /&gt;customers.Add(customer1);&lt;br /&gt;customers.Add(customer2);&lt;br /&gt;customers.Add(customer3);&lt;br /&gt;&lt;br /&gt;this.cmbTest.DataSource = objects;&lt;br /&gt;&lt;br /&gt;this.cmbTest.DisplayMember = "FullName";&lt;br /&gt;this.cmbTest.ValueMember = "ID";&lt;br /&gt;&lt;/customer&gt;&lt;/customer&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Additionally you can register for different object types a display and value member. This gives you a lot of flexibility when you have to show information of different objects in the same combobox.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To register a new type call the "RegisterType" method and pass it the type of the object, the name of the property which is used as display member and the name of the property which is used as value member.&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;this.cmbTest.RegisterType(typeof(Customer), "FirstName", "PK");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;To unregister a registered type call "UnregisterType" and pass it the type you want to unregister.&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;this.cmbTest.UnregisterType(typeof(Customer));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;To modify the display and/or value member of a registered type call "ChangeValueMember" or "ChangeDisplayMember" respectively and pass it the new name of the property you want to use.&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;this.cmbTest.ChangeDisplayMember(typeof(Customer), "FullName");&lt;br /&gt;this.cmbTest.ChangeValueMember(typeof(Customer), "LastName");&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;Of course all this operations can be performed at runtime and the changes are immediately visible in the combo.&lt;br /&gt;&lt;/div&gt;To obtain the value of the selected item, simply call "SelectedValue".&lt;br /&gt;&lt;pre class="prettyprint"&gt;Console.WriteLine(this.cmbTest.SelectedValue.ToString());&lt;br /&gt;&lt;/pre&gt;To get the selected object simply call "SelectedItem" and cast it to the correct type.&lt;br /&gt;&lt;pre class="prettyprint"&gt;Customer selectedCustomer = this.cmbTest.SelectedItem as Customer;&lt;br /&gt;if (selectedCustomer != null)&lt;br /&gt;{&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;NOTE: If the combobox has to visualize a type which is not registered it calls the ToString() method of the object and uses that string.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Now I'd like to show you the read only property. The enhanced combobox provides a read only property which disables the drop down button and changes the back color of the combobox to "Control". The read only property is not a real read only because it is not possible to select and then copy the visible text. The most important point is that you can change the fore- and backcolor of the combobox when it is in read only because it is not very easy to read the text of a disabled combo box. The images below show what I mean.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;center&gt;This is a disabled ComboBox:&lt;/center&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/DisabledComboBox.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: auto;" src="http://manfred.ramoser.googlepages.com/DisabledComboBox.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;center&gt;This is a read only ComboBox:&lt;/center&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/ReadOnlyComboBox.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: auto;" src="http://manfred.ramoser.googlepages.com/ReadOnlyComboBox.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;center&gt;You can set any color as read only back- and fore color you like:&lt;/center&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/ModReadOnlyComboBox.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: auto;" src="http://manfred.ramoser.googlepages.com/ModReadOnlyComboBox.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;That's all about my enhanced Combo Box. I hope it helps someone to achieve what he wants. If you have suggestions on how to improve it or you found a bug, feel free to leave a comment.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;You can download the DLL from &lt;a href="http://manfred.ramoser.googlepages.com/EnhancedCombo.dll" onClick="javascript: pageTracker._trackVisit ('/downloads/apps'); "&gt;here&lt;/a&gt; and simply drag and drop it to your visual studio toolbox.&lt;br /&gt;&lt;/div&gt;Or you can get the source code with a sample tool which shows how to use it from &lt;a href="http://manfred.ramoser.googlepages.com/EnhancedComboTest.zip" onClick="javascript: pageTracker._trackVisit ('/downloads/apps'); "&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-7919930924401438858?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/7919930924401438858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=7919930924401438858' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7919930924401438858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7919930924401438858'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/06/enhanced-combobox-with-readonly-and.html' title='Enhanced combobox with readonly and working value member'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-5325176841850459257</id><published>2008-06-14T15:04:00.002+02:00</published><updated>2008-06-14T15:23:34.147+02:00</updated><title type='text'>Problems with Google Earth</title><content type='html'>Lastly I updated Google Earth to the latest version and after I started it I saw the following:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/google_earth_error.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://manfred.ramoser.googlepages.com/google_earth_error.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;After searching the Internet I found the page of Google where they give some points which should be checked; such as: install the latest display driver, ...&lt;br /&gt;But I already had the latest drivers.&lt;br /&gt;While browsing trough the options of Google Earth I found that the display mode can be changed. After changing it to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;DirectX&lt;/span&gt; it worked correctly.&lt;br /&gt;&lt;br /&gt;To change the setting:&lt;br /&gt;1. go to the options&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/google_earth_options.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://manfred.ramoser.googlepages.com/google_earth_options.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;2. And then change the graphics mode to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;DirectX&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://manfred.ramoser.googlepages.com/google_earth_display_mode.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px;" src="http://manfred.ramoser.googlepages.com/google_earth_display_mode.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Related links:&lt;br /&gt;&lt;a href="http://earth.google.com/intl/en/"&gt;Google Earth&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-5325176841850459257?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/5325176841850459257/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=5325176841850459257' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/5325176841850459257'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/5325176841850459257'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/06/problems-with-google-earth.html' title='Problems with Google Earth'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-3576614051765587285</id><published>2008-05-15T17:37:00.005+02:00</published><updated>2008-05-15T17:55:07.265+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><title type='text'>Working with XML files</title><content type='html'>&lt;div style="text-align: justify;"&gt;During my work as developer I have quite often to do with XML files. They are very popular and many data exchange is done with XML and also the file format of Office 2007 is based on XML. To provide a compatibility and avoid parsing errors it is a good idea to create an XML Schema file (.xsd) which describes which structure a XML must have. This allows then to validate an XML file and check if there are errors. Since I am not very good in writing XML Schema files (and often I have no time) I use a tool of Microsoft to generate an XML Schema file from an already existing XML file. The tool is included in the .NET frameworks 1.1 to 3.5. You can simply search in your "C:\Program files" folder for "xsd.exe" and you will find it.&lt;br /&gt;&lt;/div&gt;The tool is a command line tool but very very easy to use. To get a schema out of an xml file perform the following steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Create an XML file with the desired structure (for simplicity on the desktop)&lt;/li&gt;&lt;li&gt;Search and copy the file "xsd.exe" to the desktop&lt;/li&gt;&lt;li&gt;Open a command line window (Windows key + R -&gt; type "cmd") or (Start -&gt; Run... -&gt; type "cmd")&lt;/li&gt;&lt;li&gt;Navigate to your desktop folder&lt;/li&gt;&lt;li&gt;Then type "xsd.exe myfile.xml"&lt;/li&gt;&lt;li&gt;Use the created file "myfile.xsd" as base for your xml file&lt;/li&gt;&lt;/ol&gt;Even simpler is to use the freeware tool "XMLFox Advance". You can download it from &lt;a href="http://www.xmlfox.com/"&gt;here.&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This applications helps you to create xml files and afterwards you can create the XML Schema file from it.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To validate an existing XML file against an existing XML Schema file with XMLFox you have to modify the preferences of the tool. Go to "Tools-&gt;Preferences" and check their the point "Perform validation against &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;XSD&lt;/span&gt; schema". After this you can open an XML file with the application, go to the "Script" tab and click on validate. You are asked now which &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;xsd&lt;/span&gt; file you want to use. After you selected one the validation is performed and possible errors are displayed in the list at the bottom.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-3576614051765587285?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/3576614051765587285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=3576614051765587285' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3576614051765587285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3576614051765587285'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/05/working-with-xml-files.html' title='Working with XML files'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-8405166579067673812</id><published>2008-04-26T11:29:00.006+02:00</published><updated>2008-10-18T10:57:55.367+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Who is faster??</title><content type='html'>&lt;div style="text-align: justify;"&gt;Friday 24. of April I attended a conference which was organized by the &lt;a href="http://dotnetpro.de/"&gt;dotnetpro magazine&lt;/a&gt;. The theme of the conference was &lt;a href="http://jump.dontnetpro.de/"&gt;Jump!&lt;/a&gt; and it was intended to give developers an overview of the new features of Visual Studio 2008, .Net framework 3.5 and C# 3.0. It was very interesting to see the new technologies and in which direction we are going. Something that impressed me was the new query language &lt;a href="http://en.wikipedia.org/wiki/Language_Integrated_Query"&gt;LINQ&lt;/a&gt; which can be used to query many kinds of data such as lists, xml files or databases. I was curious about the performance of this new technology and therefore I did some performance tests. I wanted to compare the traditional for loop, the nowadays mainly used foreach loop, the FindAll method of the collections class and LINQ. I executed every "method" two times because especially for LINQ this makes a big difference. The task that each "method" had to perform was to find all values which are bigger than 5 in a list of integers which contains all together 1,000,000 elements and add it to a result list. The result list contained about 400,000 elements because I filled it with a random number between 0 and 10.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Since under windows it is almost impossible to get accurate performance results because services and applications in the background interrupt my test application I run it altogether 10 times and then I took the least value for every "method". I was very impressed of the results, but first I will show you the code that I used:&lt;br /&gt;&lt;/div&gt;This is the simple for loop that everybody knows how it works.&lt;br /&gt;&lt;pre class="prettyprint"&gt;for (int i = 0; i &lt;&gt; 5)&lt;br /&gt;     result.Add(numbers[i]);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here we have the well known foreach loop which is and should be used.&lt;br /&gt;&lt;pre class="prettyprint"&gt;foreach (int num in numbers)&lt;br /&gt;{&lt;br /&gt; if (num &gt; 5)&lt;br /&gt;     result.Add(num);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This the FindAll method of the collections class. It uses a predicate to decide which elments should be returned and I used an anonymous delegate to state my condition.&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;result = numbers.FindAll(new Predicate&lt;int&gt;(delegate(int i) { return i &gt; 5; }));&lt;br /&gt;&lt;/int&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;And finally here we have the LINQ query which looks like SQL and allows to make structured queries in the code. The var keyword in front states that the compiler decides of which type the variable "res" is. In this case it will be a collection of integers.&lt;br /&gt;&lt;/div&gt;&lt;pre class="prettyprint"&gt;var res = from num in numbers&lt;br /&gt;       where num &gt; 5&lt;br /&gt;       select num;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;To talk about syntax; I prefer the LINQ syntax, because it is compact, structured and SQL like which many developers know quite well. Moreover when you have to make grouping and you do this with a foreach loop then you require much more lines of code as when you do it with LINQ. And as a speaker on the conference said:&lt;br /&gt;&lt;blockquote&gt;More lines of code contain more errors.&lt;/blockquote&gt;&lt;/div&gt;&lt;br /&gt;Ok here there is the result of my measurements:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://manfred.ramoser.googlepages.com/whoisfaster.jpg" /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;As you can see on the chart above, LINQ is by far the fastest "method" to perform such "queries". I was very impressed by the velocity. The difference between the first run and the second run lies in the implementation of LINQ. A speaker on the conference said that behind the scenes they build a binary tree and use it for searching. Therefore when this tree is build once all following queries are very very fast, also if you change the search condition.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Other things that you can see from the chart is that the good old foor loop is compared to the foreach and the FindAll "methods" the fastest. Despite this fact I will use the foreach loop in future because it is more structured and requires less thinking about the underlying array, list,... because the collection class does the work for you. I was disappointed of the performance of the FindAll method of the collection class. It was the slowest in the test. This could be because it uses predicates and anonymous delegates which may use more resources. The syntax of the FindAll is also compact and after some learning you know how to create anonymous delegates. The advantages of the methods of the collection class such as FindAll, Find, ConvertAll,... is that this features are available already under the .Net 2.0 framework and that you need only one line of code to do such "queries". The big disadvantage is as already said above that it is the slowest method to find a list of elements which satisfy a condition. For the other methods (Find, ConvertAll) I will maybe do some tests to see their performance.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you are interested to run this performance test on your own machine you can download it &lt;a href="http://manfred.ramoser.googlepages.com/WhoIsFaster.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Tools used:&lt;br /&gt;Microsoft Visual Studio 2008 Express Edition&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-8405166579067673812?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/8405166579067673812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=8405166579067673812' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/8405166579067673812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/8405166579067673812'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/04/who-is-faster.html' title='Who is faster??'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2925518134437594745</id><published>2008-04-09T17:54:00.006+02:00</published><updated>2008-04-09T18:21:57.361+02:00</updated><title type='text'>Dynamic number of parameters</title><content type='html'>&lt;div style="text-align: justify;"&gt;Lastly I realized a very interesting feature of C#; the possibility to have a dynamic number of parameters for methods. This feature can easily be used in any method by specifying the "params" keyword and then providing an array of objects which holds the parameters. This technique allows you to create interesting methods and giving you the possibility to make your code shorter and better understandable.&lt;br /&gt;First of all I'd like you to show an add method which accepts dynamic number of parameters.&lt;br /&gt;&lt;pre class="prettyprint"&gt;public static int Add(params int[] numbersToAdd)&lt;br /&gt;{&lt;br /&gt;   int sum = 0;&lt;br /&gt;   foreach (int number in numbersToAdd)&lt;br /&gt;   {&lt;br /&gt;       sum += number;&lt;br /&gt;   }&lt;br /&gt;   return sum;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;It can be called in the following two ways:&lt;br /&gt;&lt;pre class="prettyprint"&gt;int[] numbers = new int[4];&lt;br /&gt;numbers[0] = 3;&lt;br /&gt;numbers[1] = 8;&lt;br /&gt;numbers[2] = 22;&lt;br /&gt;numbers[3] = 2;&lt;br /&gt;Console.WriteLine(Add(numbers));&lt;br /&gt;/* OUTPUT&lt;br /&gt; * 35&lt;br /&gt; */&lt;/pre&gt;&lt;br /&gt;or&lt;br /&gt;&lt;pre class="prettyprint"&gt;Console.WriteLine(Add(3, 8, 22, 2));&lt;br /&gt;/* OUTPUT&lt;br /&gt; * 35&lt;br /&gt; */&lt;/pre&gt;&lt;br /&gt;Which version do you like more? I prefer the second one because I don't have to create an array of integers. Sure this method makes not really sense but it is only for demonstration purposes.&lt;br /&gt;Another interesting method could be written which is the "Concat" method. It basically concatenates every object passed as parameter to a string and returns it:&lt;br /&gt;&lt;pre class="prettyprint"&gt;public static string Concat(params object[] objects)&lt;br /&gt;{&lt;br /&gt;   StringBuilder sb = new StringBuilder();&lt;br /&gt;   foreach (object obj in objects)&lt;br /&gt;   {&lt;br /&gt;       sb.Append(obj.ToString());&lt;br /&gt;   }&lt;br /&gt;   return sb.ToString();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The usage of this method would be the following:&lt;br /&gt;&lt;pre class="prettyprint"&gt;Console.WriteLine("\n" + Concat("hello world ", 4, " ", true));&lt;br /&gt;/* OUTPUT&lt;br /&gt; * hello world 4 True&lt;br /&gt; */&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Two other methods which could be interesting are the "Copy" and "CreateAndCopy" methods. The "CreateAndCopy" method takes an object as parameter, creates a new instance of the same type and copies the properties which are specified by their name in the parameters. In addition it is a generic so that no cast is necessary and it can be used with any object. Note that when calling this method the type has not necessarily be specified because C# defers the type from the object passed.&lt;br /&gt;&lt;pre class="prettyprint"&gt;public static T CreateAndCopy&amp;lt;T&amp;gt;(T source, params string[] propertiesToCopy)&lt;br /&gt;{&lt;br /&gt;   T target = (T)System.Activator.CreateInstance(typeof(T));&lt;br /&gt;   foreach (string propertyName in propertiesToCopy)&lt;br /&gt;   {&lt;br /&gt;       PropertyInfo property = typeof(T).GetProperty(propertyName);&lt;br /&gt;       property.SetValue(target, property.GetValue(source, null), null);&lt;br /&gt;   }&lt;br /&gt;   return target;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It can be used like this:&lt;br /&gt;&lt;pre class="prettyprint"&gt;MyObject o1 = new MyObject();&lt;br /&gt;o1.Text = "hallo";&lt;br /&gt;o1.Number = 99;&lt;br /&gt;o1.Boolean = true;&lt;br /&gt;&lt;br /&gt;Console.WriteLine(o1.ToString());&lt;br /&gt;/* OUTPUT&lt;br /&gt; * MyObject:&lt;br /&gt; * Text -&gt; hallo&lt;br /&gt; * Number -&gt; 99&lt;br /&gt; * Boolean -&gt; True&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;MyObject newObj = CreateAndCopy(o1, "Text", "Boolean");&lt;br /&gt;Console.WriteLine(newObj.ToString());&lt;br /&gt;/* OUTPUT&lt;br /&gt; * MyObject:&lt;br /&gt; * Text -&gt; hallo&lt;br /&gt; * Number -&gt; 0&lt;br /&gt; * Boolean -&gt; True&lt;br /&gt; */&lt;/pre&gt;&lt;br /&gt;The "Copy" method does something similar but it accepts a destination object to which the values of the specified properties are copied to:&lt;br /&gt;&lt;pre class="prettyprint"&gt;public static T Copy&amp;lt;T&amp;gt;(T source, T destination, params string[] propertiesToCopy)&lt;br /&gt;{&lt;br /&gt;   foreach (string propertyName in propertiesToCopy)&lt;br /&gt;   {&lt;br /&gt;       PropertyInfo property = typeof(T).GetProperty(propertyName);&lt;br /&gt;       property.SetValue(destination, property.GetValue(source, null), null);&lt;br /&gt;   }&lt;br /&gt;   return destination;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;CONCLUSION:&lt;br /&gt;The possibility to specify variable number of parameters may sometimes help to make the code easier to read and better understandable but in some circumstances it is better to create a class which holds all the required values and pass an instance of it to a method.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2925518134437594745?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2925518134437594745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2925518134437594745' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2925518134437594745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2925518134437594745'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/04/dynamic-number-of-parameters.html' title='Dynamic number of parameters'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-479269626172636431</id><published>2008-04-07T18:05:00.013+02:00</published><updated>2008-12-10T12:31:32.298+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Generic progress dialog</title><content type='html'>&lt;div style="text-align: justify;"&gt;Quite often I have to perform long operations in an application and then I want to show a progress bar to the user that he can see that the application is working and how long it will take. My requirements for the progress bar dialog are:&lt;br /&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;it should be generic and therefore not be tied with the work which has to be done&lt;/li&gt;&lt;li&gt;it should not block or freeze the main application&lt;/li&gt;&lt;li&gt;the user must have the possibility to abort the operation&lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: justify;"&gt;It turned out that it is quite challenging to meet all these requirements. With different approaches I had different problems and could not fulfill my requirements. For example there was a version where the progress dialog was not updated or the user could not abort the operation. After some trying I found a quite usable solution. The main application uses a backgroundworker to do the work; this has the advantage that the computation is done in a different thread and the backgroundwoker provides cancel and progress notification. My progress bar dialog is started also in its own thread to make sure that its graphics are not blocked and updated when needed. With this "architecture" it is even possible that the main application performs some other operations while a heavy work is done and the progress shown to the user. The progress dialog provides all its functionalities through static methods which access a "private singleton". This means that the developer never gets an instance of the progress dialog and that at most one instance of the progress dialog exists. To notify the main application about the cancel event I used an event with a delegate. Therefore the main application can do what it wants when the user presses cancel.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;When the user presses cancel then a message box is shown which asks if he really wants to abort. The nice thing with this implementation is that while this message box is shown the computation goes on and is not blocked.&lt;br /&gt;&lt;br /&gt;The following code shows the progress bar, sets the title and message, assigns a method to the cancel event and starts the computation if the background worker is not already working:&lt;br /&gt;&lt;pre class="prettyprint"&gt;if (!this.backgroundWorker.IsBusy)&lt;br /&gt;{&lt;br /&gt;    this.Enabled = false; /*lock the main application*/&lt;br /&gt;    ProgressDialog.Show(max);&lt;br /&gt;    ProgressDialog.SetTitle("this is the title");&lt;br /&gt;    ProgressDialog.SetMessage("I am the message for the very long task. Please be patient and wait...");&lt;br /&gt;    ProgressDialog.CancelEvent += new ProgressDialog.CancelEventHandler(pd_CancelEvent);&lt;br /&gt;    this.backgroundWorker.RunWorkerAsync();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Important is to set the cancellation property of the background worker to true; this is best done in the designer or in the constructor of the main form:&lt;br /&gt;&lt;pre class="prettyprint"&gt;this.backgroundWorker.WorkerSupportsCancellation = true;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The computation is done in the do_work event of the background worker. Here is important that in the loop the check for the cancel event is done because otherwise the backgroundworker will not stop on cancel. To update the progress bar it is enough to call the SetValue method of the progress dialog. This is only a very stupid operation for demonstration:&lt;br /&gt;&lt;pre class="prettyprint"&gt;private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)&lt;br /&gt;{&lt;br /&gt;    for (int i = 0; i &amp;lt max; i++)&lt;br /&gt;    {&lt;br /&gt;        /*this check is needed in order to abort the operation if the user has clicked on cancel*/&lt;br /&gt;        if (this.backgroundWorker.CancellationPending)&lt;br /&gt;        {&lt;br /&gt;            e.Cancel = true;&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        ProgressDialog.SetValue(i); /*update the value*/&lt;br /&gt;        Console.WriteLine(i);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Another thing that I have to mention. In debug mode there occurs always an exception which says that this operations are not thread safe. Till now I did not had the time to look how I can make this code thread safe, but as soon as I have a thread safe version (if one exists) I will post it.&lt;br /&gt;UPDATE:&lt;br /&gt;I finally had the time to learn how to write thread safe method calls. The code below shows how it is done. First you have to check if the mehtod was called by a Thread other than the own Thread. This does the property "InvokeRequired". If so a delegate is created and the method is called with "Invoke".&lt;br /&gt;&lt;pre class="prettyprint"&gt;public static void SetTitle(string title)&lt;br /&gt;{&lt;br /&gt;    if (instance.InvokeRequired) /*if another thread called this method*/&lt;br /&gt;    {&lt;br /&gt;        SetTitleCallback s = new SetTitleCallback(SetTitle);&lt;br /&gt;        instance.Invoke(s, title);&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        instance.Text = title;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can download the full demo project &lt;a href="http://manfred.ramoser.googlepages.com/ProgressDialogDemo.zip"&gt;here&lt;/a&gt;.&lt;br&gt;&lt;br /&gt;Finally a screenshot on how my progress bar dialog looks like:&lt;br /&gt;&lt;br&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ogsDq3H2JA0/R_pPMd1p4hI/AAAAAAAAAEw/ThGW7G43SK4/s1600-h/progressbardialog1.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_ogsDq3H2JA0/R_pPMd1p4hI/AAAAAAAAAEw/ThGW7G43SK4/s400/progressbardialog1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5186544996457243154" /&gt;&lt;/a&gt;&lt;br /&gt;If you have suggestions, ideas or You know how to improve this code or if You have a thread save version You are welcome to post a comment.&lt;br /&gt;&lt;/div&gt;&lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-479269626172636431?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/479269626172636431/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=479269626172636431' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/479269626172636431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/479269626172636431'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/04/generic-progress-dialog.html' title='Generic progress dialog'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_ogsDq3H2JA0/R_pPMd1p4hI/AAAAAAAAAEw/ThGW7G43SK4/s72-c/progressbardialog1.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-7215148440662697826</id><published>2008-03-04T17:43:00.004+01:00</published><updated>2008-12-10T12:31:32.426+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>How to draw a disabled control?</title><content type='html'>&lt;div style="text-align: justify;"&gt;Recently I had to overwrite the OnPaint method of a button because I needed to draw a gradient background. My button had to display images and text. As the button should also have the disabled state where the image is gray scale I did not know how to get such an effect. After some research I found the ControlPaint class which is very useful not only in my case. It basically helps you to draw controls or part of controls such as the drop down button for a combo box and so on.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;On the following picture you can see how this may look like:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_ogsDq3H2JA0/R82DXNEgfhI/AAAAAAAAAEo/w7yoKvIthw8/s1600-h/disabledButton.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_ogsDq3H2JA0/R82DXNEgfhI/AAAAAAAAAEo/w7yoKvIthw8/s400/disabledButton.jpg" alt="" id="BLOGGER_PHOTO_ID_5173935981587365394" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The code to accomplish this is the following:&lt;br /&gt;&lt;pre class="prettyprint"&gt;public class MyButton : Button&lt;br /&gt;{&lt;br /&gt;   protected override void OnPaint(PaintEventArgs pevent)&lt;br /&gt;   {&lt;br /&gt;       Graphics g = pevent.Graphics;&lt;br /&gt;       g.FillRectangle(Brushes.White, pevent.ClipRectangle);&lt;br /&gt;       g.DrawRectangle(new Pen(Brushes.Black), pevent.ClipRectangle);&lt;br /&gt;       if (Enabled)&lt;br /&gt;       {&lt;br /&gt;           if(Image != null)g.DrawImage(Image, 0, 0);&lt;br /&gt;           g.DrawString(Text, Font, Brushes.Black, new PointF(100, 0));&lt;br /&gt;       }&lt;br /&gt;       else&lt;br /&gt;       {&lt;br /&gt;           if(Image != null)ControlPaint.DrawImageDisabled(g, Image, 0, 0, Color.Transparent);&lt;br /&gt;           ControlPaint.DrawStringDisabled(g, Text, Font, Color.Transparent, new RectangleF(100, 0, 100, 20), StringFormat.GenericDefault);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;The class ControlPaint offers also other usefull operations and you can take a look at all its members &lt;a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.controlpaint%28VS.80%29.aspx"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-7215148440662697826?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/7215148440662697826/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=7215148440662697826' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7215148440662697826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7215148440662697826'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/03/how-to-draw-disabled-control.html' title='How to draw a disabled control?'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_ogsDq3H2JA0/R82DXNEgfhI/AAAAAAAAAEo/w7yoKvIthw8/s72-c/disabledButton.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-8912227877439872592</id><published>2008-02-12T18:03:00.001+01:00</published><updated>2008-03-07T09:06:00.310+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows Vista'/><title type='text'>Wrong time under Vista in a domain</title><content type='html'>&lt;p style="text-align: justify;" class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;Recently I faced the following problem: my work computer is in a domain and unfortunately the clock of the server who provides the time for all clients is wrong. After trying to change my local clock I succeeded but only for a couple of minutes because then the old wrong time was used again. After an unsuccessful search on the Internet I found myself a solution for my problem. There exists a service which is called “Windows Time” and its description is:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="text-align: justify;" class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;blockquote&gt;“Maintains date and time synchronization on all clients and servers in the network. If this service is stopped, date and time synchronization will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start.”&lt;/blockquote&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;After stopping this service and setting its start type to manual the problem was resolved.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;      &lt;p style="text-align: justify; font-weight: bold;" class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;CAUTION:&lt;/span&gt;&lt;/p&gt;&lt;p style="text-align: justify;" class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;I do not know if switching off this service causes other things to not work correctly any more but till now I did not had any problems.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-8912227877439872592?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/8912227877439872592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=8912227877439872592' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/8912227877439872592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/8912227877439872592'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/02/wrong-time-under-vista-in-domain.html' title='Wrong time under Vista in a domain'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-3890787866014398242</id><published>2008-01-31T16:41:00.001+01:00</published><updated>2008-04-14T17:52:46.682+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Object - Relational converter</title><content type='html'>&lt;div style="text-align: justify;"&gt;Are you also bored of writing all these sql statements which are needed to persistently store your objects into a database? 80% of these sql statements are inserts, updates or deletes and can be a quite an amount of work to write them especially if you have objects with more than 10 properties. Additionally there is maybe a file which is often called something like “database manager” which contains all this stuff and grows and grows with every new class that you write.&lt;br /&gt;I was faced with the same problem and wanted to do something against this problem. If you are starting to build a project I would suggest you to use a free object relational mapper such as Castle Active Record which   takes care of all the database stuff and makes your life a lot easier. It supports by far more features and supports different DBMS. If you are already within development or you do not want to use an object relational mapper or you simply do not want to inherit all your classes from a base class (which is used often used by object relational mapper) you could consider to use my approach.&lt;br /&gt;I created a small object relational converter which is able to generate insert, update and delete statements for you based on an object that you pass as parameter. Additionally it provides the possibility to create objects from a datatable or datareader object.&lt;br /&gt;I developed this code for Microsoft SQL Server Express Edition and therefore if you use another DBMS or you need to add another data type you have to change the “ToSQL” method which is responsible to convert the different data types into their correct sql representation:&lt;/div&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;/* This method is responsible to convert the datatypes into their corresponding */&lt;br /&gt;/* sql representation. Change it if you encounter problems or if a data type */&lt;br /&gt;/* needs special treatmend. */&lt;br /&gt;private static string ToSQL(object obj)&lt;br /&gt;{&lt;br /&gt; if (obj is string || obj is Boolean)&lt;br /&gt;     return "'" + obj.ToString() + "'";&lt;br /&gt; else if (obj is DateTime)&lt;br /&gt;     return "'" + ((DateTime)obj).ToString(DATE_TIME_FORMAT) + "'";&lt;br /&gt; else if (obj is decimal)&lt;br /&gt;     return obj.ToString().Replace(',', '.');&lt;br /&gt; else&lt;br /&gt;     return obj.ToString();&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;To realize my object relational converter I used reflection and additionally the objects which should be converted have to provide some additional information such as the table name, the column name for each property and the primary key. With reflection I obtain all public, not inherited properties and use them to create the SQL statements. If you want a different behaviour such as you want to include also inherited members then you have to modify the “GetProperties” method according to your needs:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;/* This method is responsible to obtain all public, not inherited properties of an object. */&lt;br /&gt;private static PropertyInfo[] GetProperties(object obj)&lt;br /&gt;{&lt;br /&gt; return obj.GetType().GetProperties(&lt;br /&gt;     BindingFlags.DeclaredOnly |&lt;br /&gt;     BindingFlags.Instance |&lt;br /&gt;     BindingFlags.Public);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Another thing that you should know is that you have to take care to establish a connection to your DBMS and to execute the queries. My code does only the conversions.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Finally I would like to state how a class must look like in order to use my object relational converter. You have to specify for the class the table name and for each property it’s associated column name in the database.&lt;br /&gt;CAUTION: DO NOT USE RESERVED KEYWORDS OF THE SQL LANGUAGE BECAUSE THIS IS NOT CHECKED AND MAY CAUSE UNEXPECTED PROBLEMS!!&lt;br /&gt;If the property represents the primary key of the table then you have to add a true because the primary key is needed for the update and delete statement. Here is now a sample class:&lt;/div&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;[Table("myTable")]&lt;br /&gt;public class TestObject&lt;br /&gt;{&lt;br /&gt; private int table_pk;&lt;br /&gt; private string text;&lt;br /&gt; private DateTime datetime;&lt;br /&gt; private int number;&lt;br /&gt; private bool boolean;&lt;br /&gt; private decimal decimalNum;&lt;br /&gt;&lt;br /&gt; [Column("mytable_pk", true)]&lt;br /&gt; public int Table_PK&lt;br /&gt; {&lt;br /&gt;     get { return table_pk; }&lt;br /&gt;     set { table_pk = value; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [Column("datetime")]&lt;br /&gt; public DateTime Datetime&lt;br /&gt; {&lt;br /&gt;     get { return datetime; }&lt;br /&gt;     set { datetime = value; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [Column("number")]&lt;br /&gt; public int Number&lt;br /&gt; {&lt;br /&gt;     get { return number; }&lt;br /&gt;     set { number = value; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [Column("text")]&lt;br /&gt; public string Text&lt;br /&gt; {&lt;br /&gt;     get { return text; }&lt;br /&gt;     set { text = value; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [Column("boolean")]&lt;br /&gt; public bool Boolean&lt;br /&gt; {&lt;br /&gt;     get { return boolean; }&lt;br /&gt;     set { boolean = value; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [Column("decimalnum")]&lt;br /&gt; public decimal DecimalNum&lt;br /&gt; {&lt;br /&gt;     get { return decimalNum; }&lt;br /&gt;     set { decimalNum = value; }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public TestObject()&lt;br /&gt; {&lt;br /&gt;     this.table_pk = 999;&lt;br /&gt;     this.number = 5;&lt;br /&gt;     this.text = "this is a test string";&lt;br /&gt;     this.datetime = DateTime.Now;&lt;br /&gt;     this.boolean = true;&lt;br /&gt;     this.decimalNum = new decimal(1.5);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public override string ToString()&lt;br /&gt; {&lt;br /&gt;     return "pk = " + this.Table_PK + ", datetime = " + this.Datetime.ToLongDateString() + ", number = " + this.Number.ToString() + ", text = " + this.Text + ", boolean = " + this.Boolean.ToString() + ", decimal = " + this.DecimalNum.ToString() ";";&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: justify;"&gt;And here some sample code on how to use the Object - Relational converter:&lt;/div&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;TestObject a = new TestObject();&lt;br /&gt;string sql = ObjectToSqlConverter.CreateInsertStatement(a);&lt;br /&gt;sql = ObjectToSqlConverter.CreateUpdateStatement(a);&lt;br /&gt;sql = ObjectToSqlConverter.CreateDeleteStatement(a);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can download the whole project and a small sample from &lt;a href="http://manfred.ramoser.googlepages.com/ObjectRelationalConverter.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you have suggestions or you found an error feel free to write a comment and tell me about them.&lt;br /&gt;I give you this code “as is” without any warranty that it works or that it does not cause problems or delete/modify important data. Use it at your own risk in your private and commercial projects and feel free to modify it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related links:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://sqlzoo.net/"&gt;SQL Zoo (provides SQL statements for actual DBMSes)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://developer.mimer.se/validator/sql-reserved-words.tml"&gt;Reserved words in standard SQL&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msdn2.microsoft.com/en-us/library/ms131092.aspx"&gt;Microsoft SQL Server datatypes and corresponding .NET datatypes&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-3890787866014398242?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/3890787866014398242/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=3890787866014398242' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3890787866014398242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3890787866014398242'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/01/object-relational-converter.html' title='Object - Relational converter'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2267557918592196236</id><published>2008-01-31T14:45:00.001+01:00</published><updated>2008-03-07T09:10:42.046+01:00</updated><title type='text'>Hide selection in DataGridView</title><content type='html'>&lt;div style="text-align: justify;"&gt;Today I was faced at work with the problem that when there is a datagridview always the first cell/row/column depending on the selection mode is selected. I looked therefore for a property or method to have nothing selected. The data grid view provides a method called “clear selection” which can be called with&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;dataGridView1.ClearSelection();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;but for some reason this did not work for me. I tried to create a new project and to do the same thing and suddenly the “clear selection” method worked perfectly. To resolve my problem I finally used the following code:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;foreach (DataGridViewCell cell in dataGridView1.SelectedCells)&lt;br /&gt;  cell.Selected = false;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This simply takes the list of selected cells and sets the "Selected"-property to false. This can also be done with only the rows or columns with the following code snippets:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;foreach (DataGridViewRow row in dataGridView1.SelectedRows)&lt;br /&gt;  row.Selected = false;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;foreach (DataGridViewColumn column in dataGridView1.SelectedColumns)&lt;br /&gt;  column.Selected = false;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you use the version for individual cells you cover also the row and column selection. So it is not needed to have all three loops.&lt;br /&gt;&lt;/div&gt;I tried also with the code&lt;br /&gt;&lt;pre class="prettyprint"&gt;if(dataGridView1.SelectedCells.Count &gt; 0)&lt;br /&gt;   dataGridView1.SelectedCells[0].Selected = false;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Which surprisingly did produce an error in the project but worked when I tried it in the new "clean" project. Please note that this code can only be used if multiple selection is not allowed!&lt;br /&gt;I could not find out what where the differences between the empty project and my other project but if you encounter a similar behaviour the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;foreach&lt;/span&gt; loop should solve the issue; at least id did for me :-)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Tested with:&lt;br /&gt;Visual Studio 2005 Express Edition&lt;br /&gt;.NET Framework 2.0&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2267557918592196236?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2267557918592196236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2267557918592196236' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2267557918592196236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2267557918592196236'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/01/hide-selection-in-datagridview.html' title='Hide selection in DataGridView'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-7191233070937396309</id><published>2008-01-20T19:26:00.000+01:00</published><updated>2008-01-20T19:33:09.065+01:00</updated><title type='text'>Site layout improved and syntax highlighting added</title><content type='html'>&lt;div style="text-align: justify;"&gt;Thanks to the &lt;a href="http://juri-strumpflohner.blogspot.com/2008/01/finally-syntax-highlighting-on-my-blog.html"&gt;article about a syntax highlighting plug in&lt;/a&gt; of my friend &lt;a href="http://juri-strumpflohner.blogspot.com/"&gt;Juri&lt;/a&gt; I was finally able to improve the code parts on my blog. It is now better readable and in addition the syntax is highlighted which makes the code even better readable and understandable. Another change that I made which you may have noticed while reading this post, is that i enlarged the content of my page. There is now more space for the posts which make them better readable. I would like to thank my friend &lt;a href="http://juri-strumpflohner.blogspot.com"&gt;Juri&lt;/a&gt; which helped me to realize this. Thanks :-)&lt;br /&gt;&lt;br /&gt;Enjoy my blog!!&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-7191233070937396309?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/7191233070937396309/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=7191233070937396309' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7191233070937396309'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7191233070937396309'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/01/site-layout-improved-and-syntax.html' title='Site layout improved and syntax highlighting added'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-145658638491678883</id><published>2008-01-03T14:55:00.000+01:00</published><updated>2008-12-10T12:31:33.479+01:00</updated><title type='text'>Free installer for your applications</title><content type='html'>&lt;div style="text-align: justify;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ogsDq3H2JA0/R3zxPsLaW3I/AAAAAAAAAEc/7Lfx7-FUTxo/s1600-h/logo.gif"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 50px; height: 50px;" src="http://3.bp.blogspot.com/_ogsDq3H2JA0/R3zxPsLaW3I/AAAAAAAAAEc/7Lfx7-FUTxo/s400/logo.gif" alt="" id="BLOGGER_PHOTO_ID_5151257325664361330" border="0" /&gt;&lt;/a&gt;If you are a software developer like me and you developed some applications at home that you want to provide to others it is a good idea to have an installer which makes it easier to distribute your software. Since installers are often quite expensively I would like to point you to a free application that I use.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The tool is called "Create Install Free" and is available as free but also as commercial version which provides some additional features which are related mainly with branding. This tool takes a folder which contains the files of your program and creates an executable file which basically copies your files to the directory specified by the user. Additionally it provides the possibility to add a short cut to Start -&gt; Programs as well as a desktop short cut. Some other features are to add a license text which has to be accepted by the user, a readme text, an uninstaller, inserting keys into the registry and customizing the executable file symbol. An important feature is that you can select the installer language from a list of many languages to adjust it for your needs.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I used it for several projects and I can only suggest it. After all it is freeware so there is nothing that prevents you from trying it out.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Some screenshots:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here you see the output settings where you can specify the folder, the name of the executable, the icon of the executable and the type of setup.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_ogsDq3H2JA0/R3zuyMLaW2I/AAAAAAAAAEU/BR_bnk8VYi4/s1600-h/output.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_ogsDq3H2JA0/R3zuyMLaW2I/AAAAAAAAAEU/BR_bnk8VYi4/s400/output.jpg" alt="" id="BLOGGER_PHOTO_ID_5151254619834964834" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This screenshot shows the possibility of the tool to set up the installer language and the name of the application.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_ogsDq3H2JA0/R3zuyMLaW1I/AAAAAAAAAEM/Ooj3DtRfjjI/s1600-h/languages.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_ogsDq3H2JA0/R3zuyMLaW1I/AAAAAAAAAEM/Ooj3DtRfjjI/s400/languages.jpg" alt="" id="BLOGGER_PHOTO_ID_5151254619834964818" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The dialog settings allow you to provide a readme and a license file which are shown to the user during installation. Additionally you can set up some properties which dialogs should be shown.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_ogsDq3H2JA0/R3zux8LaWzI/AAAAAAAAAD8/daDULspIAMk/s1600-h/dialogs.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_ogsDq3H2JA0/R3zux8LaWzI/AAAAAAAAAD8/daDULspIAMk/s400/dialogs.jpg" alt="" id="BLOGGER_PHOTO_ID_5151254615539997490" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Here we see the Run settings  which basically lets you specify which file should be started after installation.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_ogsDq3H2JA0/R3zuyMLaW0I/AAAAAAAAAEE/AF1m0Xx_CwM/s1600-h/run.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_ogsDq3H2JA0/R3zuyMLaW0I/AAAAAAAAAEE/AF1m0Xx_CwM/s400/run.jpg" alt="" id="BLOGGER_PHOTO_ID_5151254619834964802" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This screenshot shows the uninstaller properties which gives you the ability to include an uninstaller to your application which should definitely be there.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ogsDq3H2JA0/R3zuxsLaWyI/AAAAAAAAAD0/zdgkasHakbs/s1600-h/uninstall.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_ogsDq3H2JA0/R3zuxsLaWyI/AAAAAAAAAD0/zdgkasHakbs/s400/uninstall.jpg" alt="" id="BLOGGER_PHOTO_ID_5151254611245030178" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related links:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.createinstall.com/cifree/index.htm"&gt;Homepage of Create Install Free&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-145658638491678883?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/145658638491678883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=145658638491678883' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/145658638491678883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/145658638491678883'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/01/free-installer-for-your-applications.html' title='Free installer for your applications'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_ogsDq3H2JA0/R3zxPsLaW3I/AAAAAAAAAEc/7Lfx7-FUTxo/s72-c/logo.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-715184623161502781</id><published>2008-01-03T12:08:00.000+01:00</published><updated>2008-12-10T12:31:34.006+01:00</updated><title type='text'>Portable Apps</title><content type='html'>&lt;div style="text-align: justify;"&gt;I own an external hard drive and since I have to help quite often kin and kith with their computer problems I thought it would be nice to have the most important applications with me. I looked therefore for a possibility to put applications on the external hard drive in order to run them without installation. After looking around the internet I found a very interesting tool which is called Portable Apps. It is installed on the external hard disk and an autorun mechanism is added in order to start it when the hard disk is plugged &lt;span style="" lang="EN-US"&gt;in. The Portable Apps tool adds an icon to the systray (or better notification area) which opens a menu which looks like the windows menu when clicking on start.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_ogsDq3H2JA0/R3zDMcLaWvI/AAAAAAAAADc/X4yE62NKcDU/s1600-h/menu.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_ogsDq3H2JA0/R3zDMcLaWvI/AAAAAAAAADc/X4yE62NKcDU/s400/menu.jpg" alt="" id="BLOGGER_PHOTO_ID_5151206692294908658" border="0" /&gt;&lt;/a&gt;&lt;span style="" lang="EN-US"&gt; This menu now provi&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;des access to all the different applications which are present on the external hard drive. By selecting one of them the according application is started without the need of any installation on the host computer. This has the advantage that the registry of the host computer is not affected and also no hard disk space is required. Additionally to the applications there are folders to easily access documents, music, pictures or videos.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ogsDq3H2JA0/R3zDMsLaWxI/AAAAAAAAADs/kTWJpL2Toso/s1600-h/folders.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_ogsDq3H2JA0/R3zDMsLaWxI/AAAAAAAAADs/kTWJpL2Toso/s400/folders.jpg" alt="" id="BLOGGER_PHOTO_ID_5151206696589875986" border="0" /&gt;&lt;/a&gt;&lt;span style="" lang="EN-US"&gt; Additionally it provides a backup function to easily back up or restore files on the external hard drive as well as a search functionality to search the drive, the computer or the web. At the bottom of the menu the free disk space is shown.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_ogsDq3H2JA0/R3zDMcLaWwI/AAAAAAAAADk/jDo5BqkYeuE/s1600-h/size.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_ogsDq3H2JA0/R3zDMcLaWwI/AAAAAAAAADk/jDo5BqkYeuE/s400/size.jpg" alt="" id="BLOGGER_PHOTO_ID_5151206692294908674" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;p style="text-align: justify;" class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;The list of applications in the list can be extended as needed. For some applications there exists a “Portable Apps version” which can be downloaded and installed on the homepage of portable apps but it is also possible and very easy to integrate other applications. As I tried to integrate different applications I can say that applications which do not require an activation key can be added to the list of applications because the activation key is often stored inside the registry and requires an installation routine. The most easy way to add a new application is to download it as archive without installer. It can then be put into the “PortableApps” folder on the external hard disk. The only thing to know is that in the menu there will be shown all exe files which are on the following path: Z:\PortableApps\application folder\application.exe; the name of the exe file is listed in the list of applications. Some system related applications such as firewalls can not be made portable because they have to directly interact with the underlying system and require an installation.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;A quite large and good list of portable applications can be found &lt;a href="http://portablefreeware.com/"&gt;here&lt;/a&gt;. From that site I took most of the applications that are present on my application list.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="text-align: justify;" class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;After I installed all applications that I need on the external hard drive I started to miss them when the external hard drive was not plugged in. I simply had to copy the “PortableApps” folder and the file “StartPortableApps.exe” to my local hard disk and it works fine. I like this because for example all of the sudden I get an Open Office file and to open it I do not want to install Open Office on my computer. So I start portable apps and there I have Open Office available and I can open, modify and save Open Offices files without having to install it.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;Her now a list of applications that are present on my application list:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;7-Zip Portable:&lt;/span&gt; utility for manipulating archives&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Abakt: &lt;/span&gt;simple backup utility with many configuration options&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Auto-Backup Win:&lt;/span&gt; a tool to backup all important files of a windows installation such as activation files, Outlook Express E-Mails, My Documents, and many others…&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;CCleaner:&lt;/span&gt; a tool to clean the registry, the hard disk and the autostart entries&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;CDex Application:&lt;/span&gt; a tool to rip an audio cd to mp3 files&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;ClamWin Portable:&lt;/span&gt; a portable virus scanner&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Data Recovery Application:&lt;/span&gt; a tool to recover deleted data&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;File Assasin:&lt;/span&gt; a tool to delete locked files from the system; useful to remove trojans&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Firefox Portable:&lt;/span&gt; the successful internet browser Firefox&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Gaim Portable: &lt;/span&gt;instant messenger which supports different protocols&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;JkDefrag GUI version:&lt;/span&gt; a very good defragmenter application&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Notepad++ Portable: &lt;/span&gt;text editor which provides syntax highlighting for many different programming languages&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Open Office Portable:&lt;/span&gt; open source office suite&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;ReNamer:&lt;/span&gt; a tool to rename files and folder according to rules&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Safarp:&lt;/span&gt; simple and fast uninstall utility which makes the slow windows uninstall dialog obvious&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Siginet’s Driver Grabber:&lt;/span&gt; a tool to backup all installed drivers; useful when formatting the hard drive and reinstalling windows&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;SilentNight Micro Burner:&lt;/span&gt; a tool to burn cd’s and dvd’s&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;StartUp Lite:&lt;/span&gt; a tool which checks the autostart entries and makes suggestions which entries can be removed in order to accelerate the windows start&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Sudoku Portable:&lt;/span&gt; sudoku game to pass the time&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;st1:place style="font-weight: bold;"&gt;&lt;span style="" lang="EN-US"&gt;Sumatra&lt;/span&gt;&lt;/st1:place&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt; PDF Portable:&lt;/span&gt; simple PDF reader&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;System Information for Windows: &lt;/span&gt;a very good tool to get information about hardware and software; provides additional tools such as uncovering password fields,…&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Thunderbird Portable:&lt;/span&gt; very good e-mail client&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-weight: bold;"&gt;Toucan:&lt;/span&gt; a tool &lt;/span&gt;&lt;span style="" lang="EN-GB"&gt;for &lt;span style=""&gt;advanced users&lt;/span&gt; to synchronise, backup and encrypt their data&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;span style="font-weight: bold;"&gt;VLC Media Player Portable:&lt;/span&gt; a media player which plays most of the actual video and audio formats&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;span style="font-weight: bold;"&gt;XP-AntiSpy: &lt;/span&gt;a tool which makes some settings to prevent windows from “talking” with Microsoft&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="" lang="EN-GB"&gt;&lt;span style="font-weight: bold;"&gt;Related links:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://portableapps.com/"&gt;Homepage Portable Apps&lt;/a&gt;&lt;br /&gt;&lt;a href="http://portablefreeware.com/"&gt;Homepage The Portable Freeware&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-715184623161502781?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/715184623161502781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=715184623161502781' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/715184623161502781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/715184623161502781'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2008/01/portable-apps.html' title='Portable Apps'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_ogsDq3H2JA0/R3zDMcLaWvI/AAAAAAAAADc/X4yE62NKcDU/s72-c/menu.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-7372949689555926173</id><published>2007-12-08T13:59:00.000+01:00</published><updated>2008-12-10T12:31:35.128+01:00</updated><title type='text'>Colorblindness FAQ</title><content type='html'>Hello,&lt;br /&gt;&lt;div style="text-align: justify;"&gt;as I am colorblind I would like to provide a kind of FAQ about colorblindness and how it "influences" my everyday life. First of all I would like to give you some background knowledge. The correct term for my type of colorblindness is red-green color vision deficiency which basically means that I have the biggest problems in differentiating these two colors. There also exists the yellow-blue color vision deficiency which is the same as the red-green one only with different colors but I think the red-green color vision deficiency is the most frequent one. The “heaviest” kind of colorblindness is the total colorblindness which basically means that you don’t see any colors; everything is black-white and gray.&lt;br /&gt;&lt;br /&gt;People should keep one thing in mind:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;I am colorblind but not stupid ;-)&lt;/span&gt;&lt;br /&gt;This is my answer if someone wants to trick me with some colors...&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;The first question people ask when they notice that I am colorblind is:&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Q1: What do you do at the traffic light??&lt;/span&gt;&lt;div style="text-align: justify;"&gt;A1: The traffic light is not a problem for me because the red light is at the top and the green light is at the bottom (at least in Italy) and the red light is sometimes slightly bigger than the green one as you can see in the figure below.&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_ogsDq3H2JA0/R1qWrukW-mI/AAAAAAAAACs/6dAsKD2BbKI/s1600-h/traffic+light+all+colors.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_ogsDq3H2JA0/R1qWrukW-mI/AAAAAAAAACs/6dAsKD2BbKI/s320/traffic+light+all+colors.jpg" alt="" id="BLOGGER_PHOTO_ID_5141587602575915618" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Q2: But what if the traffic lights are horizontal??&lt;/span&gt;&lt;div style="text-align: justify;"&gt;A2: unfortunately the position of the lights of a horizontal traffic light differs from country to country as the pictures below show.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ogsDq3H2JA0/R1qYhOkW-nI/AAAAAAAAAC0/F0U4qUxGlx4/s1600-h/traffic+lights+horizontal.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_ogsDq3H2JA0/R1qYhOkW-nI/AAAAAAAAAC0/F0U4qUxGlx4/s320/traffic+lights+horizontal.jpg" alt="" id="BLOGGER_PHOTO_ID_5141589621210544754" border="0" /&gt;&lt;/a&gt;So it is not that easy. But the horizontal traffic lights are not a problem for me because the contrast between the green and the red light is quite big and therefore I am able to distinguish them despite I have to be careful.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A difficult situation for me is if I drive at night and I see a traffic light from far. I see if it is green but I am not able to distinguish if it is orange or red; because I don’t see the position of the lights. But also that is no problem because I simply stop at the traffic light if it is orange or red .&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Q3: Is it curable or does there exist eyeglass&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;es which removes it?&lt;/span&gt;&lt;div style="text-align: justify;"&gt;A3: No, this “disease” or deficiency is inborn and can not be healed; there also not exists an eyeglass which removes it.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Q4: Where does it come from? Who can get it?&lt;/span&gt;&lt;div style="text-align: justify;"&gt;A4: Simply told: the color vision deficiency resides on the X chromosome. This means that if man has the defect X chromosome he is colorblind. If a woman has the defect X chromosome then he is not colorblind because the healthy X chromosome is used. If it is the case that both X chromosomes of a woman are defect then also a woman can be colorblind but as far as I know there are only very few cases on the world. The other thing is that women are the carriers for defect chromosome. This means I (as man who is colorblind) have a daughter and she has a son then the probability that the son is colorblind is very high. My direct sons are not affected.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The picture below shows how the defect X chromosome is carried. If you want more details about the backgrounds of colorblindness please refer the &lt;a href="http://en.wikipedia.org/wiki/Color_blindness"&gt;Wikipedia entry&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ogsDq3H2JA0/R1qZsOkW-qI/AAAAAAAAADM/DIJ3UXYDKTc/s1600-h/XlinkRecessive.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_ogsDq3H2JA0/R1qZsOkW-qI/AAAAAAAAADM/DIJ3UXYDKTc/s320/XlinkRecessive.jpg" alt="" id="BLOGGER_PHOTO_ID_5141590909700733602" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Q5: How do you buy your clothes?&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;A5: If I go in a store and have to buy new clothes I simply take the colors which I like. It may be the case that I don’t exactly know which color it is but I can say if I like it or not. Sometimes maybe I wear a sweater and trousers which do not fit in terms of color but I think there are worse things. And after all now I have my girlfriend which gives me tips which combinations I can wear.&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Q6: How did you realize that you are colo&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;rblind?&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;A6: This is a nice little story. In the elementary school I had to draw a crib and therefore I drew a barn with Josef, Maria and Jesus and then I colored the barn in dark green. As I showed this picture to my teacher she was horrified and asked my why I colored the barn in this color and then we (my mother and I) realized that I and also my brother are colorblind.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Q7: How does it influence your everyda&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;y life?&lt;/span&gt;&lt;div style="text-align: justify;"&gt;A7: I can say that in my everyday life I am not that restricted as other deficiencies may do and if I don’t tell people that I am colorblind or if there is a situation where I have to identify and tell a color no one would notice it.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Another point is that if the colors are in “clean” form which means that they are not mixed then normally I can differentiate them. The biggest problems I have with the color pairs red and green, dark-green and light-brown, shocking-pink and light-blue and finally violet and blue. This color pairs look very similar to me and in most cases I am not able to distinguish them.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;One of the biggest problems that I have is with the sign that a roadman has to regularize the traffic. This sign is on one side red and on the other side green as shown in the figure below.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_ogsDq3H2JA0/R1qY-ekW-oI/AAAAAAAAAC8/7P1MPZ6bMes/s1600-h/roadman+signs.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_ogsDq3H2JA0/R1qY-ekW-oI/AAAAAAAAAC8/7P1MPZ6bMes/s320/roadman+signs.jpg" alt="" id="BLOGGER_PHOTO_ID_5141590123721718402" border="0" /&gt;&lt;/a&gt;If I see both of them side by side, as in the figure above, I can say which is green one and which the red one, but if I see only one side (which is the case on the street) I am not able to tell which one the roadman is showing me. For this problem I have two approaches:&lt;br /&gt;&lt;/div&gt;The first one is that I simply do what the car before me does &lt;br /&gt;&lt;div style="text-align: justify;"&gt;The other one is if no other car is before me I simply slow down in front of the roadman and if he is showing the green one he will beckon with the sign and I know that I can go.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Another “horror” for me is the color field which is used in different software programs. The figure below shows such a color field.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_ogsDq3H2JA0/R1qWrekW-iI/AAAAAAAAACM/y3gyOvRUYug/s1600-h/color+field.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_ogsDq3H2JA0/R1qWrekW-iI/AAAAAAAAACM/y3gyOvRUYug/s320/color+field.jpg" alt="" id="BLOGGER_PHOTO_ID_5141587598280948258" border="0" /&gt;&lt;/a&gt;For example I am not able to tell if the highlighted color is light green, yellow or light orange. It could be everyone of this three. Fortunately some color fields provide the name of the color which is hovered with the mouse because otherwise I would be completely lost.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The figure below shows how a colorblind person sees the world to give you an idea. If I look at the pictures and compare them I see almost no differences. Sometimes one color is on one side a little bit darker or lighter but otherwise I don’t see any difference.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_ogsDq3H2JA0/R1qaWOkW-rI/AAAAAAAAADU/YByDdK9V8Zs/s1600-h/normal+colorblind.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_ogsDq3H2JA0/R1qaWOkW-rI/AAAAAAAAADU/YByDdK9V8Zs/s400/normal+colorblind.jpg" alt="" id="BLOGGER_PHOTO_ID_5141591631255239346" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you are curious and you would like to know if you have also color vision deficiencies I suggest you to have a look at &lt;a href="http://www.kcl.ac.uk/teares/gktvc/vc/lt/colourblindness/plate1.htm"&gt;this online test of the Kings College of London&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;If you have additional questions or you would like to tell your own experiences about colorblindness you are welcome to leave a comment.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-7372949689555926173?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/7372949689555926173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=7372949689555926173' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7372949689555926173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/7372949689555926173'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2007/12/colorblindess-faq.html' title='Colorblindness FAQ'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_ogsDq3H2JA0/R1qWrukW-mI/AAAAAAAAACs/6dAsKD2BbKI/s72-c/traffic+light+all+colors.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-831447507949388410</id><published>2007-11-26T17:54:00.003+01:00</published><updated>2009-09-01T18:13:40.247+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>C# unit testing helper</title><content type='html'>&lt;div style="text-align: justify;"&gt;As I am writing some unit tests for a C# application I found myself filling the attributes of the objects with meaningful values. With objects having 26 attributes this can be a very frustrating task and especially if you have to do it twice because you want to test the "add" and the "update" method. The other problem that I had was that I need to compare the values of all attributes of two "user" objects which again is a long task with many attributes. I decided therefore to take advantage of Reflection and letting the computer to do this nasty work.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Possible Solution:&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;I created a class called "TestHelper" which contains static methods that do exactly this work for me :-). One method fills the public, non inherited properties with random values; except for properties which name ends in "id" and properties which name is "pk". This behaviour is adjusted to my needs but can easyily be changed. The other method takes two objects as input and compares each value of their properties if the objects are of the same type; it returns true if the two objects are "equal". For the compare operations I took some code from Steve Lautenschlager (&lt;a href="http://www.cambiaresearch.com/c4/e4d91750-f604-436d-97c9-20de3e28521c/csharp-RandomProvider-Class.aspx"&gt;his code can be found here&lt;/a&gt;) and Jonas John (&lt;a href="http://www.jonasjohn.de/snippets/csharp/random-helper-class.htm"&gt;his code can be found here&lt;/a&gt;). I needed to mix this two versions because in Johns "RandomHelper" there was missing a method to generate random DateTime objects. The random fill method fills the properties according to their type as follows:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;DateTime: it puts a random date between now and 3000-01-01&lt;/li&gt;&lt;li&gt;String: it puts the name of the property plus a random string of uppercase letters of lenght 50&lt;/li&gt;&lt;li&gt;Int, long, Int32, Int64: if they are not ids or pks a random number between 0 and 999999 is set&lt;/li&gt;&lt;li&gt;Bool: a random boolean value is created&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;This behaviour can be easily changed to match your specific needs!&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;The compare method has some small disadvantage when working with DateTime objects and databases. My problem was that if in the database there was only Time datatype and it was then stored inside a DateTime object it has differed in the last 5 or 6 numbers of the Ticks number. This forced me to make this additional check but it can easily be removed and adopted to other needs.&lt;br /&gt;&lt;br /&gt;Here is the code of the TestHelper and the RandomHelper classes:&lt;br /&gt;&lt;pre class="prettyprint"&gt;public class TestHelper&lt;br /&gt;{&lt;br /&gt;    /* This method can be used to fill all public properties of an object with random values depending on their type.&lt;br /&gt;       CAUTION: it does not fill attributes that end with 'ID' or attributes which are called 'pk'. They have to be filled manually.*/&lt;br /&gt;    public static object FillAttributesWithRandomValues(object obj)&lt;br /&gt;    {&lt;br /&gt;        Type type = obj.GetType();&lt;br /&gt;        PropertyInfo[] infos = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);&lt;br /&gt;&lt;br /&gt;        foreach (PropertyInfo info in infos)&lt;br /&gt;        {&lt;br /&gt;            Type infoType = info.PropertyType;&lt;br /&gt;            if (infoType.Equals(typeof(DateTime)))&lt;br /&gt;                info.SetValue(obj, RandomHelper.RandomDateTime(DateTime.Now, new DateTime(3000, 01, 01)), null);&lt;br /&gt;            else if (infoType.Equals(typeof(String)))&lt;br /&gt;                info.SetValue(obj, info.Name + " " + RandomHelper.RandomString(50, false), null);&lt;br /&gt;            else if ((infoType.Equals(typeof(long)) || infoType.Equals(typeof(Int32)) || infoType.Equals(typeof(Int64)) || infoType.Equals(typeof(int))) &amp;&amp; !info.Name.ToLower().EndsWith("id") &amp;&amp; !info.Name.ToLower().Equals("pk"))&lt;br /&gt;                info.SetValue(obj, RandomHelper.RandomNumber(0, 999999), null);&lt;br /&gt;            else if (infoType.Equals(typeof(bool)))&lt;br /&gt;                info.SetValue(obj, RandomHelper.RandomBool(), null);&lt;br /&gt;            else if (infoType.Equals(typeof(Color)))&lt;br /&gt;                info.SetValue(obj, RandomHelper.RandomColor(), null);&lt;br /&gt;        }&lt;br /&gt;        return obj;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /* This method takes as input two objects and compares the properties of them.&lt;br /&gt;       It returns true if all the public properties of the objects (not inherited ones) are equal.*/&lt;br /&gt;    public static bool CompareObjectAttributes(object firstObject, object secondObject)&lt;br /&gt;    {&lt;br /&gt;        Type t1 = firstObject.GetType();&lt;br /&gt;        Type t2 = secondObject.GetType();&lt;br /&gt;        /*the two objects must have the same type*/&lt;br /&gt;        if (!t1.Equals(t2)) return false;&lt;br /&gt;&lt;br /&gt;        PropertyInfo[] infos1 =&lt;br /&gt;            t1.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);&lt;br /&gt;        PropertyInfo[] infos2 =&lt;br /&gt;            t2.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);&lt;br /&gt;        for (int i = 0; i &lt; infos1.Length; i++)&lt;br /&gt;        {&lt;br /&gt;            /*this if is needed because if it is a datetime it should compare only the date and the time and not the ticks*/&lt;br /&gt;            if (infos1[i].PropertyType.Equals(typeof(DateTime)))&lt;br /&gt;            {&lt;br /&gt;                DateTime firstDate = (DateTime)infos1[i].GetValue(firstObject, null);&lt;br /&gt;                DateTime secondDate = (DateTime)infos2[i].GetValue(secondObject, null);&lt;br /&gt;                /*if the datatype in the database was date then only compare the date part of the datetime object*/&lt;br /&gt;                if (firstDate.ToString().Contains("00:00:00") || secondDate.ToString().Contains("00:00:00"))&lt;br /&gt;                {&lt;br /&gt;                    if (!firstDate.Date.ToString().Equals(secondDate.Date.ToString())) return false;&lt;br /&gt;                }&lt;br /&gt;                /*otherwise compare the string representation of the two datetime objects because the ticks may differ*/&lt;br /&gt;                else&lt;br /&gt;                {&lt;br /&gt;                    if (!firstDate.ToString().Equals(secondDate.ToString()))&lt;br /&gt;                        return false;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                /*if one property value differs return false*/&lt;br /&gt;                if (!(infos1[i].GetValue(firstObject, null)).Equals(infos2[i].GetValue(secondObject, null)))&lt;br /&gt;                    return false;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /*when everything went fine the objects have the same values for their properties*/&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    /* Helper class for generating random values*/&lt;br /&gt;    public static class RandomHelper&lt;br /&gt;    {&lt;br /&gt;        private static Random randomSeed = new Random();&lt;br /&gt;&lt;br /&gt;        /* Generates a random string with the given length*/&lt;br /&gt;        public static string RandomString(int size, bool lowerCase)&lt;br /&gt;        {&lt;br /&gt;            /* StringBuilder is faster than using strings (+=)*/&lt;br /&gt;            StringBuilder RandStr = new StringBuilder(size);&lt;br /&gt;&lt;br /&gt;            /* Ascii start position (65 = A / 97 = a)*/&lt;br /&gt;            int Start = (lowerCase) ? 97 : 65;&lt;br /&gt;&lt;br /&gt;            /* Add random chars*/&lt;br /&gt;            for (int i = 0; i &lt; size; i++)&lt;br /&gt;                RandStr.Append((char)(26 * randomSeed.NextDouble() + Start));&lt;br /&gt;&lt;br /&gt;            return RandStr.ToString();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /* Returns a random number.*/&lt;br /&gt;        public static int RandomNumber(int Minimal, int Maximal)&lt;br /&gt;        {&lt;br /&gt;            return randomSeed.Next(Minimal, Maximal);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /* Returns a random boolean value*/&lt;br /&gt;        public static bool RandomBool()&lt;br /&gt;        {&lt;br /&gt;            return (randomSeed.NextDouble() &gt; 0.5);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /* Returns a random color*/&lt;br /&gt;        public static System.Drawing.Color RandomColor()&lt;br /&gt;        {&lt;br /&gt;            return System.Drawing.Color.FromArgb(&lt;br /&gt;                randomSeed.Next(256),&lt;br /&gt;                randomSeed.Next(256),&lt;br /&gt;                randomSeed.Next(256)&lt;br /&gt;            );&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /* Returns DateTime in the range [min, max)*/&lt;br /&gt;        public static DateTime RandomDateTime(DateTime min, DateTime max)&lt;br /&gt;        {&lt;br /&gt;            if (max &lt;= min)&lt;br /&gt;            {&lt;br /&gt;                string message = "Max must be greater than min.";&lt;br /&gt;                throw new ArgumentException(message);&lt;br /&gt;            }&lt;br /&gt;            long minTicks = min.Ticks;&lt;br /&gt;            long maxTicks = max.Ticks;&lt;br /&gt;            double rn = (Convert.ToDouble(maxTicks)&lt;br /&gt;               - Convert.ToDouble(minTicks)) * randomSeed.NextDouble()&lt;br /&gt;               + Convert.ToDouble(minTicks);&lt;br /&gt;            return new DateTime(Convert.ToInt64(rn));&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;UPDATE:&lt;br /&gt;This is some very simple code on how to use the UnitTestHelper. It is a very simple Console application. To use it in your unit tests adapt it to Your needs since the creation of Unit Tests is not the topic of this post.&lt;br /&gt;&lt;pre class="prettyprint"&gt;class Program&lt;br /&gt;{&lt;br /&gt;    static void Main(string[] args)&lt;br /&gt;    {&lt;br /&gt;        Person person = new Person();&lt;br /&gt;        TestHelper.FillAttributesWithRandomValues(person);&lt;br /&gt;&lt;br /&gt;        Console.WriteLine("Object with random values:");&lt;br /&gt;        Console.WriteLine(string.Format("name = {0}", person.Name));&lt;br /&gt;        Console.WriteLine(string.Format("age = {0}", person.Age));&lt;br /&gt;        Console.WriteLine(string.Format("tshirtcolor = {0}", person.TShirtColor));&lt;br /&gt;        Console.WriteLine(string.Format("birthdate = {0}", person.BirthDate));&lt;br /&gt;&lt;br /&gt;        Person p1 = new Person&lt;br /&gt;        {&lt;br /&gt;            Name = "John",&lt;br /&gt;            Age = 30,&lt;br /&gt;            BirthDate = new DateTime(2000, 10, 19),&lt;br /&gt;            TShirtColor = Color.Blue&lt;br /&gt;        };&lt;br /&gt;&lt;br /&gt;        Person p2 = new Person&lt;br /&gt;        {&lt;br /&gt;            Name = "John",&lt;br /&gt;            Age = 30,&lt;br /&gt;            BirthDate = new DateTime(2000, 10, 19),&lt;br /&gt;            TShirtColor = Color.Blue&lt;br /&gt;        };&lt;br /&gt;&lt;br /&gt;        Person p3 = new Person&lt;br /&gt;        {&lt;br /&gt;            Name = "Obama",&lt;br /&gt;            Age = 30,&lt;br /&gt;            BirthDate = new DateTime(2000, 10, 19),&lt;br /&gt;            TShirtColor = Color.Blue&lt;br /&gt;        };&lt;br /&gt;&lt;br /&gt;        Console.WriteLine("\nPerson 1 equals Person 2 = " + TestHelper.CompareObjectAttributes(p1, p2));&lt;br /&gt;        Console.WriteLine("\nPerson 2 equals Person 3 = " + TestHelper.CompareObjectAttributes(p2, p3));&lt;br /&gt;        Console.ReadLine();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This prints out the following (note that the values may differ on your machine since it are random values):&lt;br /&gt;&lt;pre&gt;Object with random values:&lt;br /&gt;name = Name BLHTVGYVHYZVQUJTIPXAWHKMCQLGGYHZMGEBZCXGBDYJCZBMGR&lt;br /&gt;age = 32895&lt;br /&gt;tshirtcolor = Color [A=255, R=32, G=148, B=35]&lt;br /&gt;birthdate = 17.07.2065 15:52:02&lt;br /&gt;&lt;br /&gt;Person 1 equals Person 2 = True&lt;br /&gt;&lt;br /&gt;Person 2 equals Person 3 = False&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-831447507949388410?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/831447507949388410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=831447507949388410' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/831447507949388410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/831447507949388410'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2007/11/c-unit-testing-helper.html' title='C# unit testing helper'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-9125560933236051923</id><published>2007-11-23T20:14:00.001+01:00</published><updated>2011-03-09T16:53:36.694+01:00</updated><title type='text'>Team Viewer</title><content type='html'>&lt;div style="text-align: justify;"&gt;&lt;a href="http://1.bp.blogspot.com/_ogsDq3H2JA0/R0cnUaxqsTI/AAAAAAAAAB4/Io_6USRQEYk/s1600-h/TeamViewer.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5136117131777847602" src="http://1.bp.blogspot.com/_ogsDq3H2JA0/R0cnUaxqsTI/AAAAAAAAAB4/Io_6USRQEYk/s320/TeamViewer.png" style="cursor: pointer; float: right; margin: 0pt 0pt 10px 10px;" /&gt;&lt;/a&gt;&lt;a href="http://manfred-ramoser.blogspot.com/2011/03/new-version-of-team-viewer.html"&gt;See also my new post about Team Viewer!&lt;/a&gt;&lt;br /&gt;As I am frequently asked by kith and kin for helping them with their computer "problems" I was since a long time looking for a good tool to resolve such small software problems over the internet. First I thought that maybe ThighVNC might be the solution but the problem there was that it is difficult or impossible to establish a connection through firewalls and routers (maybe there is a way but I was not able to do it). A day when I surfed around I found this tool which aims to "give your desktop wings". I read some comments about the programm and almost everywhere people said that this tool is the simplest remote desktop tool available and, the most important thing, it works through firewalls and routers. The best news is that there is a free version available which according to a member of TeamViewer does not lack any feature compared to commercial versions.&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;About the usage:&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Both parties have to install the software. The application provides for this an invitation e-mail which can be sent to the other person with the download link for the tool. After the successful installation both have to start the tool and the person who sits in front of the computer which is going to be remotely controlled tells the other person the ID and the password. The person who is going to access the desktop of the other computer enters the provided data and a secure connection is established. After that you can work with the other computer as if you were sitting in front of it.&lt;br /&gt;Another possibility is to install the tool as a windows service and use a predefined password which basically "eliminates" the need of someone sitting in front of the remote computer. For the ID I noticed during my tests that it is always the same for a computer so this is no problem.&lt;br /&gt;TeamViewer provides additionally a chat which unfortunately has a small bug. Every time when you are typing and the other person sends you a message the cursor of the chat is set to the first position and if you don't see it you write there. This is not very handy and this bug is already known to the TeamViewer crew and will be fixed soon. Additionally it provides a tool to send files and folders but I did not try it out.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Summary:&lt;/span&gt;&lt;br /&gt;I can only suggest this tool for people who need frequently to help other persons with computer problems or also for other purposes requiring a remote access to a computer. As the TeamViewer crew told me there are no time limitations for the usage of the tool.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Related links:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.teamviewer.com/index.aspx"&gt;TeamViewer Homepage&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-9125560933236051923?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/9125560933236051923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=9125560933236051923' title='157 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/9125560933236051923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/9125560933236051923'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2007/11/team-viewer.html' title='Team Viewer'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_ogsDq3H2JA0/R0cnUaxqsTI/AAAAAAAAAB4/Io_6USRQEYk/s72-c/TeamViewer.png' height='72' width='72'/><thr:total>157</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-1124415180491015135</id><published>2007-11-22T18:51:00.005+01:00</published><updated>2009-09-04T20:41:19.985+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Set ComboBox value member</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Problem:&lt;br /&gt;&lt;/span&gt;&lt;div style="text-align: justify;"&gt;The problem was to have assign and later read the value member of a combo box. Because this can be useful to store the primary key or id of the related object in order to get it fast.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://manfred-ramoser.blogspot.com/2008/06/enhanced-combobox-with-readonly-and.html"&gt;UPDATE: see also my latest post which deals with this issue!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Possible Solution1:&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;To assign these values a data source is needed which can be a list of any type. To make it simpler and useful I created a class which holds the value to display and the value of the value &lt;/div&gt;member.&lt;br /&gt;&lt;pre class="prettyprint"&gt;public class ComboBoxItem&lt;br /&gt;{&lt;br /&gt;private string display;&lt;br /&gt;private long value;&lt;br /&gt;&lt;br /&gt;public ComboBoxItem(string display, string value)&lt;br /&gt;{&lt;br /&gt;  this.display = display;&lt;br /&gt;  this.value = value;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public string Display&lt;br /&gt;{&lt;br /&gt;  set { display = value; }&lt;br /&gt;  get { return display; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public long Value&lt;br /&gt;{&lt;br /&gt;  set { value = value; }&lt;br /&gt;  get { return value; }&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;And here some sample code for the usage of the new class:&lt;br /&gt;&lt;pre class="prettyprint"&gt;ComboBox cb = new ComboBox();&lt;br /&gt;...&lt;br /&gt;List&amp;lt;ComboBoxItem&amp;gt; items = new List&amp;lt;ComboBoxItem&amp;gt;();&lt;br /&gt;items.Add(new ComboBoxItem("item 1", myObject.ID));&lt;br /&gt;items.Add(new ComboBoxItem("item 2", myObject2.ID));&lt;br /&gt;...&lt;br /&gt;cb.ValueMember = "Value";&lt;br /&gt;cb.DisplayMember = "Display";&lt;br /&gt;cb.DataSource = items;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note: I read on a forum that they "complained" that I am not using a generic List; but I am using a generic list, I only forgot to convert the "&amp;lt;" and "&amp;gt;" to be displayed correctly :-)&lt;br /&gt;&lt;br /&gt;This line selects the combo box item of myObject2 and shows the appropriate display member:&lt;br /&gt;&lt;pre class="prettyprint"&gt;cb.SelectedValue = myObject2.ID;&lt;/pre&gt;&lt;br /&gt;This line gets the ID of the selected item:&lt;br /&gt;&lt;pre class="prettyprint"&gt;long selectedItemID = cb.SelectedValue;&lt;/pre&gt;&lt;br /&gt;And you can retrieve the whole combo box item to do whatever you want:&lt;br /&gt;&lt;pre class="prettyprint"&gt;ComboBoxItem cbi = (ComboBoxItem) cb.SelectedItem;&lt;br /&gt;string selectedItemText = cbi.Display;&lt;br /&gt;long selectedItemID = cbi.Value;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;CAUTION:&lt;/span&gt;&lt;br /&gt;When using the data source property it is not possible to add new items to the combo box with the following code:&lt;br /&gt;&lt;pre class="prettyprint"&gt;cb.Items.Add(new ComboBoxItem("new item", 3);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Possible Solution2:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;If you do not want to create a class only for the combobox items you can also use the class "DictionaryEntry" in the namespace System.Collections. This gives you the ability to specify different datatypes for the display and value members as shown in the code below:&lt;br /&gt;&lt;pre class="prettyprint"&gt;this.comboBox1.Items.Add(new DictionaryEntry("integer", 5));&lt;br /&gt;this.comboBox1.Items.Add(new DictionaryEntry("string", "i am a string"));&lt;br /&gt;this.comboBox1.Items.Add(new DictionaryEntry("float", 5.6f));&lt;br /&gt;this.comboBox1.Items.Add(new DictionaryEntry("bool", true));&lt;br /&gt;this.comboBox1.Items.Add(new DictionaryEntry("null", null));&lt;br /&gt;this.comboBox1.Items.Add(new DictionaryEntry(1, 1));&lt;br /&gt;&lt;br /&gt;this.comboBox1.DisplayMember = "Key";&lt;br /&gt;this.comboBox1.ValueMember = "Value";&lt;br /&gt;&lt;br /&gt;this.comboBox1.DataSource = this.comboBox1.Items;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This code populates a combobox with different DictionaryEntry objects. The key can be any object and the value can also be any object. This adds the flexibility of using different display and value members in the same combobox. The last line is needed in order to get the selected value member through the according property of the combobox; because this is only "enabled" if a datasource is set. To retrieve the selected values you can use code like this:&lt;br /&gt;&lt;pre class="prettyprint"&gt;MessageBox.Show(string.Format("key: {0} - value: {1}", ((DictionaryEntry)this.comboBox1.SelectedItem).Key, this.comboBox1.SelectedValue));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you have only display - value pairs which have all the same datatypes you could use the generic class KeyValuePair&lt;tkey, tvalue=""&gt; which is in the namespace System.Collections.Generic. With this you could populate your combobox like so:&lt;br /&gt;&lt;pre class="prettyprint"&gt;this.comboBox1.Items.Add(new KeyValuePair&lt;string, int=""&gt;("customer 1", 1));&lt;br /&gt;this.comboBox1.Items.Add(new KeyValuePair&amp;lt;string, int&amp;gt;("customer 2", 2));&lt;br /&gt;this.comboBox1.Items.Add(new KeyValuePair&amp;lt;string, int&amp;gt;("customer 3", 3));&lt;br /&gt;this.comboBox1.Items.Add(new KeyValuePair&amp;lt;string, int&amp;gt;("customer 4", 4));&lt;br /&gt;&lt;br /&gt;this.comboBox1.DisplayMember = "Key";&lt;br /&gt;this.comboBox1.ValueMember = "Value";&lt;br /&gt;&lt;br /&gt;this.comboBox1.DataSource = this.comboBox1.Items;&lt;/pre&gt;&lt;br /&gt;and obtain the selected item like:&lt;br /&gt;&lt;pre class="prettyprint"&gt;MessageBox.Show(string.Format("key: {0} - value: {1}", ((KeyValuePair&amp;lt;string, int&amp;gt;)this.comboBox1.SelectedItem).Key, this.comboBox1.SelectedValue));&lt;/pre&gt;&lt;br /&gt;The advantage of this is for sure the type safety; because you do not have to cast the key or the value to the correct datatype. The disadvantage of this is that they have all to be of the same key and value type because otherwise the cast when obtaining the selecteditem would throw an exception.&lt;br /&gt;Hope this may help someone :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-1124415180491015135?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/1124415180491015135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=1124415180491015135' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/1124415180491015135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/1124415180491015135'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2007/11/set-combobox-value-member.html' title='Set ComboBox value member'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-4156137722514740369</id><published>2007-11-12T17:14:00.000+01:00</published><updated>2008-01-20T13:39:27.517+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Error during installation of service</title><content type='html'>&lt;span style="font-weight: bold;"&gt;The problem:&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;I tried to create an installer to install a windows service. The two needed installers are the ProcessInstaller and the ServiceInstaller. A requirement was to have a custom Event Log in the system for the service because there are no other ways (as far as I know) to log errors and events of a Windows service. I created therefore a new source and a new log for my application. When I tried then to install the service with "installUtil.exe" I received always an error that the source already exists on the machine and the installation was aborted and rolled back.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The solution:&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;After some trying I found out, that the ProcessInstaller creates automatically a source in the application log of the computer. As name for the source it uses the name of the project and as I had to realize I used the same name which clearly will produce the error. To solve the issue I created an EventLogInstaller and added it to the list of installers with a different name for the source and another name for the log. This solved all my problems because this installer creates now automatically the log, the source and when deinstalling, everything is removed automatically.&lt;br /&gt;To use the created log the following code can be used:&lt;br /&gt;&lt;pre class="prettyprint"&gt;EventLog.WriteEntry("sourceName", "message");&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-4156137722514740369?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/4156137722514740369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=4156137722514740369' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4156137722514740369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/4156137722514740369'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2007/11/error-during-installation-of-service.html' title='Error during installation of service'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-5741892426014020766</id><published>2007-11-03T13:08:00.000+01:00</published><updated>2007-11-03T13:18:07.626+01:00</updated><title type='text'>MonoRail</title><content type='html'>&lt;div style="text-align: justify;"&gt;In the last post I wrote about Active Record for C#. I would like to mention that from the same supplier there exist also other projects. Among them there is a framework which is called "MonoRail". As far as I understood it makes it possible to develop web applications in a Ruby on Rails like way by having MVC pattern and Action Pack. I think that this could be a big help for the development because it separates the model, the view and the controller which makes the code more readable and change tolerant. Unfortunately I did not have time to try it out, but as soon as I have some I definitely want to try it.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;I also found another framework which aims to "help a website to build itself". It is called SubSonic and tries to port the "best" things of Rails to C#. The description sounds very interesting and I definitely would like to give it a try. But the time, the time... :-)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Related Links:&lt;br /&gt;&lt;a href="http://www.castleproject.org/index.html"&gt;Castle Project Home&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.castleproject.org/monorail/index.html"&gt;MonoRail Home&lt;/a&gt;&lt;br /&gt;&lt;a href="http://subsonicproject.com/default.aspx"&gt;SubSonic Home&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-5741892426014020766?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/5741892426014020766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=5741892426014020766' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/5741892426014020766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/5741892426014020766'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2007/11/monorail.html' title='MonoRail'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2629656551466855467</id><published>2007-11-03T12:45:00.000+01:00</published><updated>2007-11-03T13:08:21.872+01:00</updated><title type='text'>Active Record for C#</title><content type='html'>&lt;div style="text-align: justify;"&gt;As I am a fan of Active Record and in the company in which I work C# is used to develop applications I looked for an Active Record implementation for C#. After some searching I found one which is called Castle Active Record. It does exactly what I want namely it provides a framework which makes it possible to use the Active Record pattern with C#.&lt;br /&gt;As I am curious I tried it out imediatly. I did the &lt;a href="http://www.castleproject.org/activerecord/gettingstarted/index.html"&gt;tutorial provided on the homepage&lt;/a&gt;.&lt;br /&gt;I had no problems with the tutorial and initially I tried it with a PostgreSQL database and I was not able to get it work. I always got an error message when I tried to let Active Record create the database schema. After some researches on the internet and some trying out I found out that I had to add a reference for the two files "Npgsql.dll" and "Mono.Security.dll" which are located at "C:\program files\PostgreSQL\8.2\Npgsql\", to my Visual Studio project. After that everything worked fine.&lt;br /&gt;To make it work with MySQL you simply have to download and install the MySQL Connector from &lt;a href="http://www.mysql.de/products/connector/odbc/"&gt;here&lt;/a&gt;. After you installed it you simply add it to your references and everything should work.&lt;br /&gt;&lt;br /&gt;The project showed me how Active Record can be used with C# and I think that it can be very useful also for commercial projects. Give it a try...&lt;br /&gt;&lt;br /&gt;I realized that the demo project is only available as VS2003 version. I will make it available as VS2005 version as soon as possible for people who have not time to write the project from scratch ;-) In my version I additionally added a search functionality which automatically iterates over all attributes of an object by using reflection and allows therfore searching in all attributes/columns.&lt;br /&gt;&lt;br /&gt;Enjoy&lt;br /&gt;&lt;br /&gt;Useful links:&lt;br /&gt;&lt;a href="http://www.castleproject.org/activerecord/index.html"&gt;Castle Active Record Home&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.mysql.de/"&gt;MySQL Home&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.postgresql.org/"&gt;PostgreSQL Home&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2629656551466855467?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2629656551466855467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2629656551466855467' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2629656551466855467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2629656551466855467'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2007/11/active-record-for-c.html' title='Active Record for C#'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-2749236754630029862</id><published>2007-11-03T11:51:00.000+01:00</published><updated>2008-12-10T12:31:36.119+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>ReadOnly controls</title><content type='html'>I had the problem, that I needed controls which can be set to ReadOnly in Visual Studio. Since I have not found a solution in the internet that fits my needs I decided to create my own controls and I would like to make them available to other persons who may need them. The controls where created with Visual Studio 2005 Express and the .NET Framework 2.0.&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;br /&gt;To make the controls even more customizable they provide in additon to the "ReadOnly" property two other properties:&lt;/div&gt;&lt;div class="n"&gt;&lt;div style="text-align: justify;"&gt; &lt;/div&gt;   &lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;ReadOnlyBackColor&lt;/span&gt; - specifies the back color of the control when it is in ReadOnly state.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;ReadOnlyForeColor&lt;/span&gt; - specifies the fore color of the control when it is in ReadOnly state.&lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: justify;"&gt; In the screenshots below you can see the impact of this properties. Only for the Checkbox the ReadOnlyBackColor is not available, because this color can be changed with the BackColor property.&lt;/div&gt;&lt;/div&gt;&lt;div class="n"&gt;  &lt;h2&gt;&lt;span style="font-size:130%;"&gt;Usage&lt;/span&gt;&lt;/h2&gt; &lt;/div&gt;&lt;div style="text-align: justify;" class="n"&gt; &lt;p&gt;To use the controls in your project simply drag and drop the dll file of the controls into your Visual Studio Toolbox.&lt;/p&gt;&lt;p&gt;Here some screenshots:&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_ogsDq3H2JA0/RyxUDMcJrLI/AAAAAAAAABo/YgU26vVYlmk/s1600-h/cache_117643902.jpg"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_ogsDq3H2JA0/RyxUDMcJrLI/AAAAAAAAABo/YgU26vVYlmk/s400/cache_117643902.jpg" alt="" id="BLOGGER_PHOTO_ID_5128566489523793074" border="0" /&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h2&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_ogsDq3H2JA0/RyxUKscJrMI/AAAAAAAAABw/c9rzg0zFpsE/s1600-h/cache_117644802.jpg"&gt;&lt;img style="cursor: pointer;" src="http://2.bp.blogspot.com/_ogsDq3H2JA0/RyxUKscJrMI/AAAAAAAAABw/c9rzg0zFpsE/s400/cache_117644802.jpg" alt="" id="BLOGGER_PHOTO_ID_5128566618372811970" border="0" /&gt;&lt;/a&gt;&lt;/h2&gt;To download the source code of the demo form and the dll file see the following link:&lt;br /&gt;&lt;a href="http://manfred-ramoser.jimdo.com/c.php"&gt;http://manfred-ramoser.jimdo.com/c.php&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-2749236754630029862?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/2749236754630029862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=2749236754630029862' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2749236754630029862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/2749236754630029862'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2007/11/readonly-controls.html' title='ReadOnly controls'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_ogsDq3H2JA0/RyxUDMcJrLI/AAAAAAAAABo/YgU26vVYlmk/s72-c/cache_117643902.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-1963515614505176894</id><published>2007-11-03T10:59:00.000+01:00</published><updated>2008-01-20T19:40:59.286+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby on Rails'/><title type='text'>Ruby on Rails</title><content type='html'>&lt;div style="text-align: justify;"&gt;As internship project for my thesis of applied computer science I developed a web application with Ruby on Rails. Since that point I am a big fan of Ruby on Rails and the used concepts such as Active Record, MVC, database migrations, scaffolds, unit- and function testing and many more. If you find some time I would stronlgy suggest to give it a try because it makes web development fast, easy and agile. "Simple" web pages can be created in a very small amount of time; but Rails provides also features for complex pages. This requires some time of vocational adjustment but then it is almost fun to create dynamic web pages.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Active Record&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div style="text-align: justify;"&gt;The most impressing thing of Rails was the built in support for the Active Record pattern. This is the short definition of what it is:&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.&lt;br /&gt;&lt;a href="http://martinfowler.com/eaaCatalog/activeRecord.html"&gt;Martin Fowler&lt;/a&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;i&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;/i&gt;&lt;/blockquote&gt;&lt;div style="text-align: justify;"&gt;The idea behind is very very interesting. It mainly states that you take care of building the model with its objects and the relations between them and Active Record maps then automatically to an underlying database management system. The big advantages of this are that you can change the database when you like because you are not bounded to a specific DBMS; another big advantage is that you do not have to write any SQL which reduces errors and safes you a lot of code and maybe also a class which is called DBManager ;-).&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To start you simply "tell" Active Record which is the database that you use, the name of the catalog and the user with which to connect to the DBMS. After that you create so called migration scripts which are written in Ruby and are used to create the needed tables in the database; you can also create the database tables manually or with SQL but I found that this was the easiest way. After the successful creation of the tables you can start coding. It is very simple to do that as you can see by this example:&lt;br /&gt;&lt;br /&gt;This code creates a new user and stores it in the database:&lt;br /&gt;&lt;pre class="prettyprint"&gt;user = User.new()&lt;br /&gt;user.name = "uname"&lt;br /&gt;user.passwor = "mypassword"&lt;br /&gt;user.create&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This code updates an existing user and stores the changes in the database:&lt;br /&gt;&lt;pre class="prettyprint"&gt;user = User.find(3)&lt;br /&gt;user.name = "newName"&lt;br /&gt;user.update&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This code destroys a user:&lt;br /&gt;&lt;pre class="prettyprint"&gt;user = User.find(3)&lt;br /&gt;user.destroy&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It is as simple as this and you do not have to write any SQL statements.&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Finally some usefull links to get started with Ruby on Rails:&lt;br /&gt;&lt;a href="http://www.rubyonrails.org/"&gt;&lt;span style="text-decoration: underline;"&gt;Ruby on Rails Home&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://rubyforge.org/projects/rubyinstaller/"&gt;One click Ruby installer&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.onlamp.com/pub/a/onlamp/2006/12/14/revisiting-ruby-on-rails-revisited.html"&gt;Tutorial&lt;/a&gt; (not tried by myself)&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;a href="http://www.rubyonrails.org/"&gt;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-1963515614505176894?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/1963515614505176894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=1963515614505176894' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/1963515614505176894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/1963515614505176894'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2007/11/ruby-on-rails.html' title='Ruby on Rails'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8340788719090141711.post-3558335216630635984</id><published>2007-11-03T10:46:00.000+01:00</published><updated>2007-11-03T10:59:35.319+01:00</updated><title type='text'>Hello world!</title><content type='html'>Hello out there. I decided to start a Blog where I post my opinions and ideas.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Since I work in a small software company in south tirol I think that I will face with problems during development and I would like to post here possible solutions that I/we found which may be useful also for other people...&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8340788719090141711-3558335216630635984?l=manfred-ramoser.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://manfred-ramoser.blogspot.com/feeds/3558335216630635984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8340788719090141711&amp;postID=3558335216630635984' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3558335216630635984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8340788719090141711/posts/default/3558335216630635984'/><link rel='alternate' type='text/html' href='http://manfred-ramoser.blogspot.com/2007/11/hello-world.html' title='Hello world!'/><author><name>Manfred</name><uri>http://www.blogger.com/profile/14884047895668798987</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
