<?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-19004283</id><updated>2011-04-21T13:52:56.621-07:00</updated><title type='text'>Kudos's Tech Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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>75</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-19004283.post-114875891126515448</id><published>2006-05-27T12:39:00.000-07:00</published><updated>2006-05-27T12:41:51.303-07:00</updated><title type='text'>New Blog</title><content type='html'>I really don't like blogger so I have decided to setup a blog on my own server (what else are web servers good for?). The new URL is:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blogs.solidhouse.com/david.woods/"&gt;http://blogs.solidhouse.com/david.woods/ &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As such all new posts will be found at the URL above&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114875891126515448?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114875891126515448/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114875891126515448' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114875891126515448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114875891126515448'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/new-blog.html' title='New Blog'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114804958709162795</id><published>2006-05-19T07:38:00.000-07:00</published><updated>2006-05-19T07:39:47.106-07:00</updated><title type='text'>Vista takes 15GB?</title><content type='html'>&lt;span class="SystemDoesNotMeetsMinimumRequirementsTitle"&gt;I just ran the vista upgrade advisor (tells you if you have the requirements to run vista). and was shocked to get this error:&lt;br /&gt;&lt;br /&gt;We're sorry, but your PC  cannot currently install and run the core experiences of Windows Vista.  &lt;/span&gt;&lt;br /&gt;However, you may be able prepare your computer for Windows Vista by  upgrading your PC hardware. &lt;p&gt;&lt;span class="ComponentsDoNotMeetMinimum"&gt;You will need to take the following  actions to run Windows Vista.&lt;/span&gt;&lt;/p&gt; &lt;div class="ResultsSummaryDiv"&gt;&lt;span class="ActionItem"&gt;Additional hard drive  storage&lt;/span&gt;&lt;br /&gt;&lt;div class="ResultsDetailTableExplainationCell"&gt;&lt;b&gt;15GB free space required &lt;span class="tiny-bold"&gt;(Your computer currently has 3.53 GB)&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;You will  either need to:&lt;br /&gt;a) upgrade your hard drive to increase its capacity, or &lt;br /&gt;b) create additional free space on your existing drive by removing unwanted  files.&lt;br /&gt;If you decide to upgrade your hard drive, we recommend 40GB capacity  at minimum for premium editions of Windows Vista. Contact your PC retailer to  see if an upgrade is available.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Why in the world in an OS 15GB? How many DVD's is it comming on? Or better yet how many CD's for the non DVD people.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114804958709162795?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114804958709162795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114804958709162795' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114804958709162795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114804958709162795'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/vista-takes-15gb.html' title='Vista takes 15GB?'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114787988964568959</id><published>2006-05-17T08:21:00.000-07:00</published><updated>2006-05-17T08:31:29.660-07:00</updated><title type='text'>Backups are important</title><content type='html'>I think backups are usually the most poorely done thing in any organization. Even if you have a backup solution it is very rarely checked to ensure that it is working.&lt;br /&gt;&lt;br /&gt;1. How often are backups verified / tested. If possible I recommend taking a system and restoring your backup to it and see if everyone can still work.&lt;br /&gt;&lt;br /&gt;2. How old are your tapes? They don't last forever you know. I don't know the average life but I am guessing at 1-2 years depending on rotation.&lt;br /&gt;&lt;br /&gt;3. Do you have a rotation (i.e. a tape for every day of the week)? If yesterday is corrupt then going back 2 days is not terrible&lt;br /&gt;&lt;br /&gt;4. Are your backups stored offsite? If not, set your building on fire as an exercise and see how well you can recover.&lt;br /&gt;&lt;br /&gt;5. Do you have a backup server? Replacement hardware can take time to install and configure. I recommend having a spare server on site that you can restore to (or better yet clone your data to it periodically and have a spare with all the data).&lt;br /&gt;&lt;br /&gt;Backups are not just about computers.&lt;br /&gt;&lt;br /&gt;Do you have a backup internet connection?&lt;br /&gt;&lt;br /&gt;Do you have a backup air conditioner? (one of my clients had all their servers go down last night as the air conditioner crapped out).&lt;br /&gt;&lt;br /&gt;Do you have backup power? Even if it is only 15 minutes that  could be all the time you need to save your work&lt;br /&gt;&lt;br /&gt;Do you have a backup backup opperator. If only one person knows how to backup / restore then just hope they don't get sick.&lt;br /&gt;&lt;br /&gt;Do you have your servers off the floor? Floods and computers don't mix. I had a client whos air conditioners drain pipe (to drain away the condensation) break and flooded the server room. Thankfully the servers and power connections were off the floor.&lt;br /&gt;&lt;br /&gt;If you are not confident that you could wipe all the computers in your organization and be back at work 100% in a quick period of time (1-2 days depending on size of organization) then its time to re examine your backup solution(s).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114787988964568959?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114787988964568959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114787988964568959' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114787988964568959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114787988964568959'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/backups-are-important.html' title='Backups are important'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114779042334406495</id><published>2006-05-16T07:40:00.000-07:00</published><updated>2006-05-16T07:40:23.386-07:00</updated><title type='text'>Starting an application as another user</title><content type='html'>&lt;a href="http://www.developerfusion.co.uk/show/5679/"&gt;http://www.developerfusion.co.uk/show/5679/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114779042334406495?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114779042334406495/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114779042334406495' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114779042334406495'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114779042334406495'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/starting-application-as-another-user.html' title='Starting an application as another user'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113790366151356210</id><published>2006-05-15T10:53:00.000-07:00</published><updated>2006-05-15T10:56:17.820-07:00</updated><title type='text'>My Toolbox</title><content type='html'>-FxCop. Great tool for keeping code consitant&lt;br /&gt;-Nunit. Unit testing tool&lt;br /&gt;-CopyAsHTML (great for blogging / documentation)&lt;br /&gt;-DataSet Quick Watch (http://www.codeproject.com/csharp/DSWatch/DSWatchSetup.zip)&lt;br /&gt;  Great tool for seeing a dataset in a datagrid while debugging&lt;br /&gt;-Firefox&lt;br /&gt;     &lt;span style="font-weight: bold;"&gt;FFox plugins&lt;/span&gt;&lt;br /&gt;    -IE Tab (opens a page that is only ie compatible within firefox)&lt;br /&gt;    -Sage (nice little newsreader)&lt;br /&gt;    -Web Developer (if you do work with the web get this... period)&lt;br /&gt;    -Adblocker&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113790366151356210?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113790366151356210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113790366151356210' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113790366151356210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113790366151356210'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/my-toolbox.html' title='My Toolbox'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114771399109738528</id><published>2006-05-15T10:12:00.000-07:00</published><updated>2006-05-15T10:26:31.116-07:00</updated><title type='text'>What we are doing wrong</title><content type='html'>I recently had a rant about us as developers not having a clue what we are doing. I want to try and narow this down into a few areas that I think need improvement.&lt;br /&gt;&lt;br /&gt;1. Testing. We don't take a step back and look at different scenarios. Whenever I develop something it is to do a task and that is what I test. I never test a method to see how it react when different data then the scenario is added.&lt;br /&gt;&lt;br /&gt;2. UI. I never make an application useable. Its not because I hate the user but that my emphasis is on functionality. We almost need to look at the interface as requiring the most functionality and designing a good clean interface that is user friendly. I need to start designing programs thinking that the end user is going to be my grandma or something like that.&lt;br /&gt;&lt;br /&gt;3. Data. My applications are filled with garbage data. I need to find a better way to put realistic data into my applications. One thing to be carefull of is copying production data into development as this may violate privacy laws depending on where you live (seriously).&lt;br /&gt;&lt;br /&gt;4. Load &amp; Concurrency. I barely ever test my applications in high load situations nor do I test what would happen if two methods got run at the same time. I ran some tests on one application and was supprised at the number of deadlocks I got in the database (then again it might have been my testing tool)&lt;br /&gt;&lt;br /&gt;5. Design. I really think most of us don't know how to design an application. We all have different views and opinions (or are lacking in this department). I think we need to start looking at all the different ways of doing things and start to reach a concensus.&lt;br /&gt;&lt;br /&gt;6. Client Interaction. I find that the client is not involved enough and is upset when they don't get what they asked for. This is one reason I really like agile for having the client heavily involved in the development project.&lt;br /&gt;&lt;br /&gt;7. Unit Testing. I  have found this to be  such a  usefull tool / practice. Since I started using it I have found that the quality of my releases has been higher in that there are few if any regression bugs and I feel more confident making changes to existing code. I really think that if you have not tried having unit tests of some kind in an application that you should.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114771399109738528?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114771399109738528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114771399109738528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114771399109738528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114771399109738528'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/what-we-are-doing-wrong.html' title='What we are doing wrong'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114744396710043774</id><published>2006-05-12T07:11:00.000-07:00</published><updated>2006-05-15T09:52:46.723-07:00</updated><title type='text'>Why ,NET applications use so much memory</title><content type='html'>You may notice that even a small application seems to consume a lot of memory on your system. I am strating to think that this is because the runtime reserves two 16mb segments for the small and large object heaps. I assume that you don't often see it as 32mb segments in task manager as a lot of it will be unused and paged to disk. Its just a theory though :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114744396710043774?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114744396710043774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114744396710043774' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114744396710043774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114744396710043774'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/why-net-applications-use-so-much.html' title='Why ,NET applications use so much memory'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114730536077703816</id><published>2006-05-10T16:54:00.000-07:00</published><updated>2006-05-10T16:56:00.843-07:00</updated><title type='text'>Permission generation script</title><content type='html'>Here is a hany security script that will generate the grant execute / select /delete permissions on all objects in your database if you have the need to do so:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Declare @RevokeSQL varchar(1000)&lt;br /&gt;Declare @GrantSQL varchar(1000)&lt;br /&gt;declare @EveryoneRoleName varchar(30)&lt;br /&gt;&lt;br /&gt;set @EveryoneRoleName='Public'&lt;br /&gt;&lt;br /&gt;set nocount on&lt;br /&gt;&lt;br /&gt;select P.ID, U.Name as UserName, o.name as ObjectName,&lt;br /&gt;case P.ProtectType&lt;br /&gt;when 204 then 'GRANT_W_GRANT'&lt;br /&gt;when 205 then 'GRANT'&lt;br /&gt;when 206 then 'REVOKE'&lt;br /&gt;end as ProtectType,&lt;br /&gt;case p.action&lt;br /&gt;when 26 then 'REFERENCES'&lt;br /&gt;when 178 then 'CREATE FUNCTION'&lt;br /&gt;when 193 then 'SELECT'&lt;br /&gt;when 195 then 'INSERT'&lt;br /&gt;when 196 then 'DELETE'&lt;br /&gt;when 197 then 'UPDATE'&lt;br /&gt;when 198 then 'CREATE TABLE'&lt;br /&gt;when 203 then 'CREATE DATABASE'&lt;br /&gt;when 207 then 'CREATE VIEW'&lt;br /&gt;when 222 then 'CREATE PROCEDURE'&lt;br /&gt;when 224 then 'EXECUTE'&lt;br /&gt;when 228 then 'BACKUP DATABASE'&lt;br /&gt;when 233 then 'CREATE DEFAULT'&lt;br /&gt;when 235 then 'BACKUP LOG'&lt;br /&gt;when 236 then 'CREATE RULE'&lt;br /&gt;end as PermissionGranted&lt;br /&gt;into #Temp&lt;br /&gt;from sysprotects P&lt;br /&gt;inner join sysusers U on P.UID = U.UID&lt;br /&gt;inner join sysobjects O on P.ID=O.ID where&lt;br /&gt;P.uid=0 and o.Type&lt;&gt;'S' and&lt;br /&gt;(O.Name not like 'sync%'&lt;br /&gt;and O.Name not like 'sys%'&lt;br /&gt;and O.Name not like 'dt_%')&lt;br /&gt;-- just added the funky syntax for o.name filters&lt;br /&gt;order by UserName, ObjectName&lt;br /&gt;&lt;br /&gt;DECLARE cur CURSOR&lt;br /&gt;READ_ONLY&lt;br /&gt;FOR Select UserName, PermissionGranted, ObjectName from #Temp&lt;br /&gt;&lt;br /&gt;DECLARE @name varchar(40)&lt;br /&gt;DECLARE @ProtectType varchar(100)&lt;br /&gt;DECLARE @ObjectName varchar(100)&lt;br /&gt;OPEN cur&lt;br /&gt;&lt;br /&gt;FETCH NEXT FROM cur INTO @name, @ProtectType, @ObjectName&lt;br /&gt;WHILE (@@fetch_status &lt;&gt; -1)&lt;br /&gt;BEGIN&lt;br /&gt;IF (@@fetch_status &lt;&gt; -2)&lt;br /&gt;BEGIN&lt;br /&gt;--create has a slightly different syntax, so we have to branch&lt;br /&gt;--here&lt;br /&gt;if @ProtectType like 'Create%'&lt;br /&gt;begin&lt;br /&gt;set @GrantSQL ='Grant ' + @ProtectType + ' to ' + @EveryoneRoleName&lt;br /&gt;print @GrantSQL&lt;br /&gt;-- exec(@GrantSQL)&lt;br /&gt;-- set @RevokeSQL ='Revoke ' + @ProtectType + ' on [' + @ObjectName + '] from ' + @Name&lt;br /&gt;-- print @RevokeSQL&lt;br /&gt;--exec(@RevokeSQL)&lt;br /&gt;end&lt;br /&gt;else&lt;br /&gt;begin&lt;br /&gt;set @GrantSQL ='Grant ' + @ProtectType + ' on [' + @ObjectName + '] to ' + @EveryoneRoleName&lt;br /&gt;print @GrantSQL&lt;br /&gt;-- exec(@GrantSQL)&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;END&lt;br /&gt;FETCH NEXT FROM cur INTO @name, @ProtectType, @ObjectName&lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;CLOSE cur&lt;br /&gt;DEALLOCATE cur&lt;br /&gt;&lt;br /&gt;--clean up the working table&lt;br /&gt;drop table #Temp&lt;br /&gt;&lt;br /&gt;set nocount off&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114730536077703816?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114730536077703816/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114730536077703816' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114730536077703816'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114730536077703816'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/permission-generation-script.html' title='Permission generation script'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114726920585430947</id><published>2006-05-10T06:47:00.000-07:00</published><updated>2006-05-10T06:53:25.903-07:00</updated><title type='text'>SQL: Dynamic SQL Avoidance</title><content type='html'>I have several stored procs that take a flag that tells them wether to show expired records or not and usually looks something like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;DECLARE @ShowExpired tinyint&lt;br /&gt;SET @ShowExpired = 1&lt;br /&gt;&lt;br /&gt;declare @sql varchar(1000)&lt;br /&gt;set @sql = 'SELECT * FROM TABLE'&lt;br /&gt;IF @ShowExpired = 1&lt;br /&gt;    set @sql = @sql + ' WHERE eff_end_dt is NULL"&lt;br /&gt;execute (@sql)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;While this works fine if I loose the advantages of stored procs and if I rename a table and recreate the procedure (I periodically recreate all procedures to test this) then I will not see any error.&lt;br /&gt;&lt;br /&gt;Instead I came up with this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;DECLARE @ShowExpired tinyint&lt;br /&gt;SET @ShowExpired = 1&lt;br /&gt;&lt;br /&gt;select * from Table&lt;br /&gt;where ((@ShowExpired=1) or (@ShowExpired=0 and eff_end_dt is null))&lt;br /&gt;&lt;br /&gt;basically all the is happening if @ShowExpired=1 then everything gets returned. But if @ShowExpired=0 then only records that have a null end date are returned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114726920585430947?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114726920585430947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114726920585430947' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114726920585430947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114726920585430947'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/sql-dynamic-sql-avoidance.html' title='SQL: Dynamic SQL Avoidance'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114722522056872001</id><published>2006-05-09T18:39:00.000-07:00</published><updated>2006-05-09T18:40:20.586-07:00</updated><title type='text'>SQL Coding standards</title><content type='html'>I love the formatting of SQL from this article.&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/sql/default.aspx?pull=/library/en-us/dnsqlpro04/html/sp04l9.asp"&gt;http://msdn.microsoft.com/sql/default.aspx?pull=/library/en-us/dnsqlpro04/html/sp04l9.asp &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114722522056872001?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114722522056872001/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114722522056872001' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114722522056872001'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114722522056872001'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/sql-coding-standards.html' title='SQL Coding standards'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114719959262787909</id><published>2006-05-09T11:32:00.000-07:00</published><updated>2006-05-09T11:33:12.656-07:00</updated><title type='text'>Interesting Article</title><content type='html'>http://blogs.msdn.com/oldnewthing/archive/2006/05/09/593605.aspx&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114719959262787909?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114719959262787909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114719959262787909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114719959262787909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114719959262787909'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/interesting-article.html' title='Interesting Article'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114713106279891747</id><published>2006-05-08T16:26:00.000-07:00</published><updated>2006-05-08T16:31:02.823-07:00</updated><title type='text'>Refactoring an enterprise application</title><content type='html'>I am in the process of refactoring a fair sized com application that is consumed by many other applications. When the system was designed all data between the com system and the clients was via a dataset interface. This has caused lots of issues with naming, required fields, etc. so here is my plan to refactor it out while still preserving client compatability&lt;br /&gt;&lt;br /&gt;1. As I do work create objects that are representitive of the entities being passed in&lt;br /&gt;2. Create transformer objects that change the method from a dataset to an object and back again (testing this thoroughly of course)&lt;br /&gt;3. Change the Data layer to use these new objects.&lt;br /&gt;4. Migrate this up to the business layer (this is the layer that is exposed to the clients)&lt;br /&gt;5. Take the incomming dataset and apply the transformer to create the objects&lt;br /&gt;6. Expose the newobjects as overloaded methods that new clients can now consume&lt;br /&gt;7. Depricate the old dataset methods and eventually remove them&lt;br /&gt;&lt;br /&gt;I think it will work. I will let you know if it does in about... 2 years :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114713106279891747?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114713106279891747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114713106279891747' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114713106279891747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114713106279891747'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/refactoring-enterprise-application.html' title='Refactoring an enterprise application'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114692911907352028</id><published>2006-05-06T07:57:00.000-07:00</published><updated>2006-05-06T08:26:58.366-07:00</updated><title type='text'>Daves 9 rules of business</title><content type='html'>Here are a few of my rules for business. Some of these don't apply to programmers but they are observations I wanted to share.&lt;br /&gt;&lt;br /&gt;1. Business certificates can make a lot of money.&lt;br /&gt;     -For one  they are usually gifts to people and either the receiver will not have a use for the item&lt;br /&gt;       or else they will loose it. I have no stats to back this up the number of unused gift certs out there must be high.&lt;br /&gt;     -The only issue is the cost of implemeting a gift cert program. If the costs are minimal then go         for it&lt;br /&gt;&lt;br /&gt;2. If a customer is unhappy do whatever you can to make them happy&lt;br /&gt;&lt;br /&gt;3. If a customer wants to leave and you can not make them happy then do everything you can to get rid of them. If you drag your heals on releasing them from something then they will complain louder and louder to not only you but their friends and clients giving you a bad name.&lt;br /&gt;&lt;br /&gt;4. If a customer is constantly unhappy or trying to devalue your service, get rid of them. Clients that are a pain cost more money and take away time from keeping your good customers and developing new ones. Also the stress applied to you and your staff from negative clients is a real downer. My rule of thumb is if you do not pick up the phone due to the number on the call display get rid of them.&lt;br /&gt;&lt;br /&gt;5. Charge what it is worth. I have cut my prices for friends and companies that are tight on cash and have always resented it. If they want a quality project then they should pay for it. This is why the term is called cutting your own throat and it is sooo acurate.&lt;br /&gt;&lt;br /&gt;6. The first person to a market with a new idea will always succeed. If you come in second with an idea then no one will know about you. This is why mcdonalds, IBM, coca-cola are so well know and have the best sales even though their markets are ripe with competition. I have no idea why this phenomenon occurs only that everywhere I look it seems to be true. Basically what I am saying is that if you are copying someone else you can never expect to usurp them.&lt;br /&gt;&lt;br /&gt;7. If you are working more than 8 hours a day to make ends meet you are not charging enough. Eventually you will burn out and get behind. Start charging more. If you only get one contract at double the price of 2 you will work fewer hours and soon be able to bring on more staff.&lt;br /&gt;&lt;br /&gt;8. Good management knows what is going on. If you have employees keep in touch with what is going on. Even more so get to know them. Have them out for a beer after work. If an employee likes there manager they will be happier, not complain about money, and have greater job satisfaction. This is a key to employee retainment.&lt;br /&gt;&lt;br /&gt;9. Don't lie to your client to make them happy. If you tell your customer a project will be done in a week and takes a month they will be upset. If you tell them it will take two months and you have it done in a month then they will be happy they got it so early. If you tell them it will take four months and it is done in one then they will feel that you charged them for four months of work but only did one. Lies seem to compound themselves until finally you have to come clean with your client. If you tell them bad news as soon as you can they will probably be a little upset but at least aware. If you tell them their project failed because of something you discovered 6 months ago you are going to loose a client.&lt;br /&gt;&lt;br /&gt;10.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114692911907352028?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114692911907352028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114692911907352028' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114692911907352028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114692911907352028'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/daves-9-rules-of-business.html' title='Daves 9 rules of business'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114670057812117250</id><published>2006-05-03T16:48:00.000-07:00</published><updated>2006-05-03T20:12:05.396-07:00</updated><title type='text'>ASP.NET validators and other browsers</title><content type='html'>I developed a little app last night that used the builtin ASP.NET validators. Now that I am running firefox as my default browser I have discovered that the validators client script does not work in anything other than IE. The reason for this is that the BaseValidator class (all validation controls derive from this class) have methods the emit javascript to do the validation. This script also contains an array of validator controls and summaries that looks like this:&lt;br /&gt;&lt;br /&gt;var Page_ValidationSummaries =  new Array(document.all["ValidationSummary1"]);&lt;br /&gt;var Page_Validators =  new Array(document.all["RequiredFieldValidator1"], document.all["RequiredFieldValidator2"], document.all["RequiredFieldValidator3"], document.all["RequiredFieldValidator4"], document.all["RegularExpressionValidator1"], document.all["RequiredFieldValidator5"]);&lt;br /&gt;&lt;br /&gt;And therin lies the problem. Only IE uses document.all every other browser I know off does not recognize document.all. Instead what should have been used is document.getElementById to get the controls.&lt;br /&gt;&lt;br /&gt;There are two ways I see to fix this. The first is to just download a replacement validator suite like this &lt;a href="http://aspalliance.com/glav/downloads/domvalidators.zip"&gt;free one&lt;/a&gt;. I have not tried it (so I appreciate some feedback if you do). Instead I am going to do things the hard way and fix the javascript issues by creating a class that emits compatable javascript for all browsers. I do it the hard way so that I can better understand what is going on internally and seems to help me build better solutions.&lt;br /&gt;&lt;br /&gt;Update. It is now 9pm and I am frustrated. I have made a ton of progress towards this goal but am having issues with the runtime not wanting to run my override (I assume this is because it thinks firefox can only do html 3.2 not 4.0 like the all mighty IE). I am going to leave this for a while and get some beer therapy and maybe try more tommorow. I will post the code once I get a solution figured out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114670057812117250?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114670057812117250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114670057812117250' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114670057812117250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114670057812117250'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/aspnet-validators-and-other-browsers.html' title='ASP.NET validators and other browsers'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114666669598861746</id><published>2006-05-03T07:08:00.000-07:00</published><updated>2006-05-03T07:31:36.486-07:00</updated><title type='text'>Paradigm Shift</title><content type='html'>I like to post on technical things but the state of the industry has really been getting to me so I thought I would right a post about it.&lt;br /&gt;&lt;br /&gt;In summary: Most of us have no clue what we are doing.&lt;br /&gt;&lt;br /&gt;I say this because of my experiences in the past year. I can teach anyone to code. Its really not that hard to do the basics but to make a large application is where people stumble (myself included). The reasons for this is that there is no set way to do things. Everyone has their own way and this is harmfull. What if every engineer had their own way to do foundation. We would need tons of unique tools for that foundation, tons of training for the people pouring the foundation, and tons of money as every process is unique. I think that this is what happening in our industry.&lt;br /&gt;&lt;br /&gt;Over the past while of reading books like Refactoring and Patters Of Enterprise Application Architecture by Martin Fowler, talking with developers, watching webcasts. I see a whole new way to develop and I have been programming professionaly for the last 5 years.&lt;br /&gt;&lt;br /&gt;As I start using some of these amazing techniques I can't be saddend to know that most developers out there have no clue about these. I have shown the model view presenter pattern to a fiew developers and they are blown away. I personally can not stop using it (I built a simple contact submittion form last night using it just because I like it so much). Interface driven development is the best thing I have started using lately and is a great way to allow decoupling of contract and implementation. Honestly I feel like I am seeing how to program for the first time since I did basic on my apple II.&lt;br /&gt;&lt;br /&gt;This is a new and rapidly changing field. Historically look at being a gunsmith. It starts that everyone has their own way to manufacture a firearm from raw materials and it is pretty much how everyone else is doing it but its slow (i.e. coding in a basic language) . Then some technology comes out like a metal lathe (i.e. .NET) and now we can build things in our own custom way but faster. We have hit the point in the industry that any developer can build something small quite quickly and reliably but when we need to work togeather or build a large application most of us are in the dark.&lt;br /&gt;&lt;br /&gt;What we need to do is follow the guns and use the concept of interchangeable parts and starting to look at how to make our projects work better with other developers and other projects. Unfortunately I don't know how to do this other than having us educate each other and share more in the community of doing things in better ways.&lt;br /&gt;&lt;br /&gt;&lt;/rant&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114666669598861746?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114666669598861746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114666669598861746' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114666669598861746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114666669598861746'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/05/paradigm-shift.html' title='Paradigm Shift'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114624148119752261</id><published>2006-04-28T09:10:00.000-07:00</published><updated>2006-04-28T09:24:41.230-07:00</updated><title type='text'>TDD Last night</title><content type='html'>Normally I don't post about life stuff but this is code related. Last night I went to the first edmonton .NET  user group meeting and had a great time.  Jean-Paul Boodhoo was the presenter and did a great talk about test driven development amongst other things.&lt;br /&gt;&lt;br /&gt;I have read about TDD and all sorts of patterns books but found them hard to know when to apply them in the real world. JP's presentation was a begging to middle (we ran out of time unfortunately) coding sesssion using TDD to build an application. The cool thing was that we built the application from the presentation tier down pretending that other teams were doing the data / domain / service layer work.&lt;br /&gt;&lt;br /&gt;Here were some of the cool things covered:&lt;br /&gt;Rhino Mock - A cool framework to build mock objects&lt;br /&gt;Resharper - A great time saver when doing TDD&lt;br /&gt;Interface driven development - I have to admit that this presentation made this concept so crystal clear I might make a full post about it.&lt;br /&gt;Model View Presenter - This changed my life. Check JP's blog for his videos on this.&lt;br /&gt;&lt;br /&gt;I see know what TDD is and how powerfull it is for keeping your code clean and simple (if you have not heard it before TDD is not a testing model, it is a design model).&lt;br /&gt;&lt;br /&gt;My only complaint about the presentation is that it was not long enough. The presentation was 2 hours but I would have loved to see the project be finished. But beer, food, and hockey were calling! :)&lt;br /&gt;&lt;br /&gt;Links:&lt;br /&gt;JP's blog - &lt;a href="http://www.jpboodhoo.com/blog/"&gt;http://www.jpboodhoo.com/blog/&lt;/a&gt;&lt;br /&gt;Edmonton .NET user group - &lt;a href="http://www.edmug.net/"&gt;http://www.edmug.net/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114624148119752261?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114624148119752261/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114624148119752261' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114624148119752261'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114624148119752261'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/04/tdd-last-night.html' title='TDD Last night'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114528773619782388</id><published>2006-04-17T08:28:00.000-07:00</published><updated>2006-04-17T08:28:56.223-07:00</updated><title type='text'>Globalization Link</title><content type='html'>Here is an interesting article about number grouping in different countries.&lt;br /&gt;&lt;br /&gt;http://blogs.msdn.com/oldnewthing/archive/2006/04/17/577483.aspx&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114528773619782388?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114528773619782388/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114528773619782388' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114528773619782388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114528773619782388'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/04/globalization-link.html' title='Globalization Link'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114407526579136263</id><published>2006-04-03T07:35:00.000-07:00</published><updated>2006-04-03T08:21:45.216-07:00</updated><title type='text'>Canadian Law And The Web Part 3: Peer 2 Peer</title><content type='html'>Now this is not really a development talk but there is a lot of concern about the legalities of downloading music in Canada and I thought I would set the record straight on it. Part of Canadian copyright grants a fair use for copying things for personal enjoyment as long as it is not shared or sold publically.&lt;br /&gt;&lt;br /&gt;We actually pay a levy on all media (i.e. blank cassette tapes, blank cds and dvds). This levy is a tax to compensate artists for revenue lost to the copying of their works. So technically we already pay to make copies of music. Unfortunately from what I have read is that this money is not making it to the artists at all. The levy has generated about $120 million in the past 5 years. About 25 percent of that has been distributed to the artists.&lt;br /&gt;&lt;br /&gt;This still does not mean that it is right for us to download music in my opinion. I had heard of an ISP that included access to a music download service as part of its fee which I really liked the idea of (I can't remember the name of the ISP though). I am very against buying a CD from the store now as it is too expensive and too crappy. I like the idea of only getting the 2 songs from a CD that are good. It encourages the artist to make better music and the labels to reduce prices. Unfortunately instead of seeing this trend these record labels are suing the people downloading music.&lt;br /&gt;&lt;br /&gt;In 2004 BMG Canada Inc. Attempted to learn the identities of users who have infringed copyright by trading music on the internet in the case BMG Canada Inc. v. John Doe. This case had a few issues with the evidence they presented (i.e. how a kazaa user was tied to an IP address, not contacting the software manufacturer to see if they could find the identities of the users of the software, along with the time gap between gathering the evidence and bringing it to court).&lt;br /&gt;&lt;br /&gt;When BMG Canada Inc. requested the identities they must compensate the ISPs for the expenses arising out of discovering the account holder. The ISPs responded that this was a very intensive process and hard to determine who was using a certain IP at a given time. These records are not held indefinately and might be purged at any time. They also stated that all they could find out was who the account holder was. Not who did the actuall downloading in the home.&lt;br /&gt;&lt;br /&gt;The act of downloading is interesting also. Under Section 80 of the Copyright Act it is allowable for a person to make a copy of a musical work for private use of the person who makes the copy. Thus downloading a song for personal use is not an infringement under Canadian Copyright Law.&lt;br /&gt;&lt;br /&gt;The act of distribution is key in this case also. Under Candian Copyright a person must authorize the copying of files. Simply placing a file in a shared folder does not count as authorization. It is akin to placing a photocopyer in a public library. If you were to send out copies or advertise the copies (i.e. chat rooms, websites, etc.) you would be infringing on copyright.&lt;br /&gt;&lt;br /&gt;In the end this case was thrown out for many reasons.&lt;br /&gt;The main ones were:&lt;br /&gt;1. Downloading the song is not an infringement&lt;br /&gt;2. Placing the song in a shared folder is not an infringement&lt;br /&gt;&lt;br /&gt;Things that weakened the case even further:&lt;br /&gt;1. The company who found the Kazaa and iMesh users did not present enough evidence on how this information was gathered.&lt;br /&gt;2. The time between the information gathering and the court case was long with no explination.&lt;br /&gt;3. Due to the time length and difficulty of finding who was using an IP at a given time innocent people could have been wrongly accused.&lt;br /&gt;4. The actuall person using the computer at that time could not be identified based on the IP address.&lt;br /&gt;&lt;br /&gt;One interesting technicallity arrises out of this. If I were to lend you a CD and you made a copy that would be legal under the copyright act. If I took my CD, copied it, and gave it to you that would tecnically be distribution and would be a copyright infringement.&lt;br /&gt;&lt;br /&gt;I am unsure how this would apply with me emailing you an mp3. In this case when is copying occurring? I would think it happens on my computer as when it leaves my computer a duplicate is made and sent to you. I think I would have to make it available to you via a P2P application or an FTP server to make it legal.&lt;br /&gt;&lt;br /&gt;As you can see the industry does not like this and copyright reform is on the way right now.&lt;br /&gt;-&lt;span style="font-weight: bold;"&gt;World Intellectual Propery Organization Performances and Phonograms Treaty&lt;/span&gt; has some items about making a work publically available but is not currently in a Canadian copyright law. This would probablly make it an infringement to share music to the public&lt;br /&gt;-&lt;span style="font-weight: bold;"&gt;Bill C-60&lt;/span&gt; is waiting to be passed that ammends Candaian copyright law. I have not had a chance to look this over yet but I am sure there are some interesting changed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114407526579136263?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114407526579136263/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114407526579136263' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114407526579136263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114407526579136263'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/04/canadian-law-and-web-part-3-peer-2.html' title='Canadian Law And The Web Part 3: Peer 2 Peer'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114392898728563655</id><published>2006-04-01T14:59:00.000-07:00</published><updated>2006-04-01T15:04:12.916-07:00</updated><title type='text'>Setting JPEG image quality</title><content type='html'>I have many applications that create thumbnails or manipulate images. When I save these as jpegs the quality kind of sucks though. Took me a while but found a way to set it by way of using one of the image.save overloads to pass the encoder to use (in this case the jpeg encoder) and parameters to that encoder.&lt;br /&gt;&lt;br /&gt;Here is the method taht finds the right encoder based on mime type:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt;     &lt;span class="cb1"&gt;private&lt;/span&gt; &lt;span class="cb1"&gt;static&lt;/span&gt; ImageCodecInfo GetEncoderInfo(String MimeType)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt;         {&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;             ImageCodecInfo Result = &lt;span class="cb1"&gt;null&lt;/span&gt;;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;             ImageCodecInfo[] Encoders = ImageCodecInfo.GetImageEncoders();&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt;             &lt;span class="cb1"&gt;for&lt;/span&gt;(&lt;span class="cb1"&gt;int&lt;/span&gt; i = 0; Result == &lt;span class="cb1"&gt;null&lt;/span&gt; &amp;&amp;amp; i &lt;&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt;             {&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt;                 &lt;span class="cb1"&gt;if&lt;/span&gt; (Encoders[i].MimeType == MimeType)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    8&lt;/span&gt;                 {&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    9&lt;/span&gt;                     Result = Encoders[i];&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   10&lt;/span&gt;                 }&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   11&lt;/span&gt;             }&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   12&lt;/span&gt;             &lt;span class="cb1"&gt;return&lt;/span&gt; Result;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   13&lt;/span&gt;         }&lt;/p&gt;&lt;/div&gt; &lt;br /&gt;Here is the code that actually saves the file:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   30&lt;/span&gt;     EncoderParameters encoderParameters;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   31&lt;/span&gt;             encoderParameters = &lt;span class="cb1"&gt;new&lt;/span&gt; EncoderParameters(1);&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   32&lt;/span&gt;             encoderParameters.Param[0] = &lt;span class="cb1"&gt;new&lt;/span&gt; EncoderParameter(Encoder.Quality, 100L);&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   33&lt;/span&gt;             img.Save(ms, GetEncoderInfo("image/jpeg"), encoderParameters );&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;The thing that tripped me up for a while was the 100L for the quality. If I left the L off then the quality would not be changed strangely enough.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114392898728563655?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114392898728563655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114392898728563655' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114392898728563655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114392898728563655'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/04/setting-jpeg-image-quality.html' title='Setting JPEG image quality'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114392423431487991</id><published>2006-04-01T13:39:00.000-07:00</published><updated>2006-04-01T13:43:54.316-07:00</updated><title type='text'>~ = friend</title><content type='html'>One of those nice little things not many people know about is the use of a ~ character in relative URLS. The ~ allows you to access the document root.&lt;br /&gt;&lt;br /&gt;i.e.  &lt;a href="~/showlog.aspx"&gt;Show the log&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If this was in a virtual directory called sampleapp the url would render to be&lt;br /&gt;&lt;br /&gt;http://localhost/sampleapp/showlog.aspx&lt;br /&gt;&lt;br /&gt;but when deployed to a production and not in a sample app it would be&lt;br /&gt;http://www.sampleapp.com/showlog.aspx&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if we just had a link without the tilde like this:&lt;br /&gt;i.e.  &lt;a href="/showlog.aspx"&gt;Show the log&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;then it would work in production but in development it would render to the root of the server&lt;br /&gt;i.e. http://localhost/showlog.aspx&lt;br /&gt;instead of the vdir like we want :)&lt;br /&gt;&lt;br /&gt;Just a little trick. I am not sure if this works on apache or not or if IIS is finding those ~'s and replacing them for the user.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114392423431487991?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114392423431487991/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114392423431487991' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114392423431487991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114392423431487991'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/04/friend.html' title='~ = friend'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114381812236508919</id><published>2006-03-31T08:06:00.000-07:00</published><updated>2006-03-31T08:15:22.383-07:00</updated><title type='text'>Sending a file to the client</title><content type='html'>&lt;div&gt;Sometimes you need to send a file to the client by them clicking a link. If it is stored on your hard drive (appologies for the bad formatting. busy day today):&lt;br /&gt;&lt;p&gt;&lt;span&gt;private sub SendFile(fileName as string)&lt;br /&gt;dim filepath as string = Server.MapPath("files") &amp; fileName&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;filepath = &lt;/span&gt;Server.UrlPathEncode(filepath) 'encoded to remove special characters i.e. spaces&lt;/p&gt;&lt;p&gt;response.clear() 'clear the output buffer&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Response.ContentType = &lt;span&gt;"application/binary"&lt;/span&gt; 'binaries are almost always downloaded. If it was set to excel for an excel file the browser might try to open it in the browser window&lt;/p&gt;&lt;p&gt;Response.AddHeader(&lt;span&gt;"Content-Disposition"&lt;/span&gt;, &lt;span&gt;&lt;/span&gt;&lt;span&gt; "attachment;filename=" + &lt;/span&gt;&lt;span&gt;fileName&lt;/span&gt;) 'This is what tells the browser the filename to prompt the user with when they save it&lt;/p&gt;&lt;p&gt; Response.TransmitFile(filePath) 'transmit the file (internally reads and sends the file to the client &lt;/p&gt;&lt;p&gt;Response.Flush() 'write everything in the buffer to the client&lt;br /&gt;&lt;/p&gt; &lt;p&gt;Response.End() 'end the response so nothing else gets sent to the browser&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;end sub&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;Often you have these files in an area outside of the web root or in a database. If you have this scenario you can use a&lt;br /&gt;&lt;br /&gt;Response.BinaryWrite(bytearray)&lt;br /&gt;&lt;br /&gt;to send a bytearray to the client. You can easily get a byte array by reading a file with a filestream and then copying that to a byte array. Wish I had time to post on that today but sadly I do not.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114381812236508919?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114381812236508919/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114381812236508919' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114381812236508919'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114381812236508919'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/sending-file-to-client.html' title='Sending a file to the client'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114374388555720949</id><published>2006-03-30T10:37:00.000-07:00</published><updated>2006-03-30T12:31:37.520-07:00</updated><title type='text'>Canadian Law And The Web Part 2: Copyright</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Copyright Basics&lt;/span&gt;&lt;br /&gt;Copyright is the right granted to an individual to protect a peice of work he/she has created. This applies to literary, dramatic, musical, and artistic works.&lt;br /&gt;&lt;br /&gt;Copyright is automatic. Meaning that once you have created a work it is already protected by copyright and you have rights to defend that work from being copied.&lt;br /&gt;&lt;br /&gt;Copyright protection does not extent to ideas, facts, or information. Meaning that if I came up with an idea for an invention and even wrote it down. It does not prevent someone else from creating that idea. The only thing they can not do is copy what I wrote down. Patents can be used to protect these kinds of ideas (but that is outside the scope of this document).&lt;br /&gt;&lt;br /&gt;An interesting thing I discovered is that lectures count as literary works and are also protected. Lecutures includes addresses, speaches, and sermons. I know this really does not apply but just thought it to be interesting.&lt;br /&gt;&lt;br /&gt;Copyright lasts. A copyrighted work maintains its copyright 25 years after the author dies. The copyright is passed as part of the estate.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Ownership&lt;/span&gt;&lt;br /&gt;In essence the person who created a work is its author and therefore owns the copyright. This is not necessarily true when you are in the employ of a contract of another person&lt;br /&gt;&lt;br /&gt;Section 13(3) where the author of a work was in the employment of some other person under a contract of service or apprenticeship and the work was made in the course of his emplyoment by that person, the person by whom the auther was employed shall, in the absence of any agreement to the contrary, be the first owner of the copyright.&lt;br /&gt;&lt;br /&gt;There are exclusions though for newspaper, magazine, or similar periodical contributions in this section but that does not apply for us.&lt;br /&gt;&lt;br /&gt;If you are in the hire of someone and do work the person who hired you holds the copyright!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Granting Rights to Others&lt;/span&gt;&lt;br /&gt;As the owner of a copyright you can grant rights for other people to use, perform,  create derivitive works, or full rights. These agreements must be in writting to make them binding. By granting someone the right to use or perform your work they can replicate your work in its entirety. Derivitive works give the right for the licencee to modify the original and re-use it. Full or Exclusive rights give the licencee full rights to the work and can do whatever they want and relicence it to others if they so choose.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What This Means&lt;/span&gt;&lt;br /&gt;-If you are hired by someone to do work they own the copyright on the work you performed for them.&lt;br /&gt;-If you take content (be it text or images) from another person without their written permission and place it on a site you are commiting a copyright infringment.&lt;br /&gt;-If you design something on your own (not hired by someone else) and a client wishes to use it. You should sell them a license to use your work.&lt;br /&gt;-If you grant someone a licence to use your work (but not make derivitive works) and they modify it, they have commited an infringement.&lt;br /&gt;-Using music or images on a site that you do not have written permission to use is an infringement.&lt;br /&gt;-If you built something for a client that has hired you and then find another client that needs the same thing. You can not sell them the item you produced without written consent from the original client you did the work for (as they hold the copyright).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;How To Protect Yourself as a Developer&lt;/span&gt;&lt;br /&gt;-Ensure that you have rights to all of the works you are using in your project.&lt;br /&gt;-Have a contract with your client that outlines who owns what.&lt;br /&gt;-In your contract have a clause that ensures both parties are contributing works that they have rights to.&lt;br /&gt;-I personally like the idea of stating in my contracts for projects that I am the owner of the copyright and the client has been granted a license to use the website. I also like to grant them the right to make derivitive works on the item in case they want to make changes in the future. This way they can go to another developer and have it done in case we had a falling out.&lt;br /&gt;-The best way is to consult with a lawyer. From my reading most laws for the brick and mortar world apply to the internet world.&lt;br /&gt;-If hiring subcontractors to do work ensure that the subcontractors only use works that they have rights to.&lt;br /&gt;-Make sure that you have rights to the work that the subcontractors do. I ensure that I have at least the right to make derivitive works on everything they send me.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Questions&lt;/span&gt;&lt;br /&gt;Q. Who owns source files, psd's, fla's, etc.?&lt;br /&gt;A. If you have hired someone to do the work then you have full rights to those works as you have paid for them to be created.&lt;br /&gt;&lt;br /&gt;Q. How can I verify that I am not infringing on someone elses copyright?&lt;br /&gt;A. There is no real way to do this that I know of. I would do a search on the interenet for content that I am using on a project and make sure that I can not find it. Usually if you infringe on someones copyright then they will notify you and ask you to change / remove the offending matterial. This is the best case (who wants to go to court anyways?)&lt;br /&gt;&lt;br /&gt;If you have any more please send them.&lt;br /&gt;&lt;br /&gt;DISCLAIMER: I am not even close to a lawyer. This is not legal advice. Consult with a lawyer in any matter you have about law.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114374388555720949?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114374388555720949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114374388555720949' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114374388555720949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114374388555720949'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/canadian-law-and-web-part-2-copyright.html' title='Canadian Law And The Web Part 2: Copyright'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114367054154372262</id><published>2006-03-29T14:39:00.000-07:00</published><updated>2006-03-29T15:15:41.593-07:00</updated><title type='text'>Canadian Law And The Web Part 1: Accessability</title><content type='html'>I have a mild interest in law and how it affects me. I have been working with technology for most of my life and there is still not much I can find about how the law relates to what we do in everyday cases. In a series of posts I am going to make I will talk about some of them.&lt;br /&gt;&lt;br /&gt;DISCLAIMER: I am not a lawyer and  the following  guides are for information only. They should not be treated as legal advice. Contact a lawyer for any legal questions you might have. Don't play with fire. It is hot. You might get burned. Yada yada yada.&lt;br /&gt;&lt;br /&gt;Accessability:&lt;br /&gt;&lt;br /&gt;From what I could find there is no laws about enabling your website for disabled persons. You might think of this as a good thing but just becuase there is not a law specifically for something means that another one can be adapted to it.&lt;br /&gt;&lt;br /&gt;For instance:&lt;br /&gt;Section 15 of the Canadian Charters of Rights and Freedom(http://laws.justice.gc.ca/en/charter/) state that "every individual is    equal before the law"&lt;br /&gt;Section 5 of the     &lt;a href="http://laws.justice.gc.ca/en/H-6/"&gt;&lt;cite&gt;Canadian Human Rights Act&lt;/cite&gt;&lt;/a&gt; state that access to goods or services can not be denied on the basis of descrimination&lt;br /&gt;&lt;br /&gt;The Human Rights Act also states that descrimination is unacceptable wether it is intentional or not.&lt;br /&gt;&lt;br /&gt;Basically this sums up to: "ignorance is not an excuse" and "brick and mortar law" could be applied to the the internet in this case. I am going to recommend that you try to ensure that you make websites as available as possible to the public.&lt;br /&gt;&lt;br /&gt;Here is the W3s guide on website accessability: http://www.w3.org/TR/WAI-WEBCONTENT/&lt;br /&gt;&lt;br /&gt;Honestly, reading through the guide has a lot of helpfull tips even for designing a website for the general public as well and it does not take that much extra time to develop with.&lt;br /&gt;&lt;br /&gt;(most information for this article was found here: http://www.zvulony.com/accessibility.html)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114367054154372262?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114367054154372262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114367054154372262' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114367054154372262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114367054154372262'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/canadian-law-and-web-part-1.html' title='Canadian Law And The Web Part 1: Accessability'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114365577096465066</id><published>2006-03-29T11:00:00.000-07:00</published><updated>2006-03-29T11:09:30.996-07:00</updated><title type='text'>Determining if a session has expired</title><content type='html'>The first thing to discuss is Session.IsNewSession() this returns true if a session was just created on this request.&lt;br /&gt;&lt;br /&gt;On the first request to a page this will return true.&lt;br /&gt;durring the session it will return false&lt;br /&gt;after a timeout error occurs this will also return true (the session no longer exists so it gets recreated).&lt;br /&gt;&lt;br /&gt;So we know that if IsNewSession() returns true that either this is a new request or the session has timed out.&lt;br /&gt;&lt;br /&gt;Now the way that sessions work is the server sends the browser a cookie with the session ID. On every request the client sends this cookie and the server loads your session.&lt;br /&gt;&lt;br /&gt;On the first request to a page the browser will not send a cookie&lt;br /&gt;durring the session it will send the cookie&lt;br /&gt;after a timout occurs it will still send the cookie&lt;br /&gt;&lt;br /&gt;So now we can determine if we have a timeout by using this code:&lt;br /&gt;&lt;br /&gt;If Session.IsNewSession Then&lt;br /&gt;            Dim strCookieHeader As String = Request.Headers("Cookie")&lt;br /&gt;            If strCookieHeader.Length &gt; 0 AndAlso strCookieHeader.IndexOf("ASP.NET_SessionId") &gt; 0 Then&lt;br /&gt;          'redirect to timeout page here&lt;br /&gt;end if&lt;br /&gt;&lt;br /&gt;I put this code into a basepage that all of my pages that use session data inherit from.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114365577096465066?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114365577096465066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114365577096465066' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114365577096465066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114365577096465066'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/determining-if-session-has-expired.html' title='Determining if a session has expired'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114365084976711907</id><published>2006-03-29T09:46:00.000-07:00</published><updated>2006-03-29T09:47:29.766-07:00</updated><title type='text'>Why not to depend on client side validation</title><content type='html'>A great example on why not to depend on client side validation only:&lt;br /&gt;http://thedailywtf.com/forums/65974/ShowPost.aspx&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114365084976711907?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114365084976711907/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114365084976711907' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114365084976711907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114365084976711907'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/why-not-to-depend-on-client-side.html' title='Why not to depend on client side validation'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114364753308051947</id><published>2006-03-29T08:28:00.000-07:00</published><updated>2006-03-29T09:41:34.723-07:00</updated><title type='text'>GUIDs and Databases</title><content type='html'>For those of you who don't know what a GUID is it is a 128 bit value that is "Unique across space and time". A GUID looks like this: B2658C9D-A76G-4D72-B0E4-B732332408D6. There garanteed uniqueness has been used by the com+ system in windows for years. This is why two com components with the same name can be installed without conflicting (they each have a GUID that keeps them seperate).&lt;br /&gt;&lt;br /&gt;Developers seem to be pessimistic about GUID collissions in their systems. I just have to say that it will not happen. As I said com+ has been using this forever and I have never heard of a GUID collission ever. GUID itself stands for Globally Unique IDentifier. i.e. accrosss the globe no one else has the same GUID.&lt;br /&gt;&lt;br /&gt;Now onto why these are usefull in databases:&lt;br /&gt;&lt;br /&gt;1. Merging of data&lt;br /&gt;If you have 2 databases with the same tables but are currently seperated (i.e. an identical sales database in 2 seperate offices). If you want to combine these into a data warehouse you will have issues with numerical identies colliding. If you used a GUID then there would be no conflict.&lt;br /&gt;If you are using replication then GUIIDS are your friends for this same reason&lt;br /&gt;&lt;br /&gt;2. Security&lt;br /&gt;If you look at this query string&lt;br /&gt;editpage.aspx?userId=23526&lt;br /&gt;I would guess that chaning that userId up or down one would allow me to be another person on the system. Granted it is bad design to expose this information to the user (hide it in session state instead so the client never sees it). But as I always say security should be layered. If we used a GUID for our userIds we would have a query string like this:&lt;br /&gt;editpage.aspx?userId=B2658C9D-A76G-4D72-B0E4-B732332408D6&lt;br /&gt;By its very deffinition it would be impossibly for anyone to brute force this (they could never generate another GUID that matches one in our system because they are globally unique).&lt;br /&gt;3. Disconnected Data&lt;br /&gt;Typically when creating data we create the records, insert it, then read back the numerical key that sql has created. By using a GUID we can set our key in data to be that GUID and fire it off to the database knowing for sure that no other ID like it will exist in the datbase.&lt;br /&gt;4. Integer Data Space&lt;br /&gt;You can run out of integers in a database (I can't remember the limit) for IDs but by using GUIDs you can have limitless number of IDs without fear of exhaustinga limit.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The Cons&lt;br /&gt;Speed: It takes time to generate a number that is that unique. This takes CPU cycles&lt;br /&gt;Readability: It is easier to read and type a query like select * from table where ID=30 than select * from table where ID='B2658C9D-A76G-4D72-B0E4-B732332408D6'&lt;br /&gt;Space: GUIDs are larger than integers (4 times larger) and take up more space. I am of the adage that storage is cheap now so unless you are going to have a massive massive massive database this does not concern me that much&lt;br /&gt;Page Splits: Due to the size of GUIDs they can contribute to page splits in SQL&lt;br /&gt;Searching and Comparison: It takes a bit longer to compare two guids when searching that it does an integer&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114364753308051947?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114364753308051947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114364753308051947' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114364753308051947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114364753308051947'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/guids-and-databases.html' title='GUIDs and Databases'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114347488334807384</id><published>2006-03-27T08:48:00.000-07:00</published><updated>2006-03-27T08:54:43.576-07:00</updated><title type='text'>Removing while iterating through a collection</title><content type='html'>Often times developers want to loop through a collection and filter out items. Unfortunatley they get the error that they can not change the contents while enumerating it. There are 2 solutions to this problem&lt;br /&gt;&lt;br /&gt;1. Copy the records to be removed to an array or collection of some sort and then remove them in a second loop&lt;br /&gt;&lt;br /&gt;2. Run it through a for loop backwards and remove the entries as needed&lt;br /&gt;&lt;br /&gt;       Dim refRow As dataRow&lt;br /&gt;        For i As Integer = ds.tables(0).Rows.Count - 1 To 0 Step -1&lt;br /&gt;            If ds.tables(0).rows(i).item("refundeeId")  = refundeeId Then&lt;br /&gt;                ds.tables(0).Rows.RemoveAt(i)&lt;br /&gt;            End If&lt;br /&gt;        Next&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If we ran the loop forward instead of backwards and removed 10 out of 100 items when we got to the 90th iteration of the loop it would crash. This is because the size of the table has been reduced to 90 instead of 100 so when we try to access ds.tables(0).rows(91) it actually no longer exists.&lt;br /&gt;&lt;br /&gt;By going backwards we are counting down and removing items. So if we removed 10 out of 100 again our table has only 90 records in it BUT we are now accessing ds.tables(0).rows(9) which still exists instead of try ds.tables(0).rows(91) which does not.&lt;br /&gt;&lt;br /&gt;Hope that makes sense! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114347488334807384?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114347488334807384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114347488334807384' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114347488334807384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114347488334807384'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/removing-while-iterating-through.html' title='Removing while iterating through a collection'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114298170257958528</id><published>2006-03-21T15:44:00.000-07:00</published><updated>2006-03-21T15:55:02.606-07:00</updated><title type='text'>Javascript rounding weirdness</title><content type='html'>I have this in code:&lt;br /&gt;&lt;br /&gt;var total = parseFloat(txtGLItemAmount1.value) + parseFloat(txtGLItemAmount2.value)&lt;br /&gt;&lt;br /&gt;when I insert 110.16 and 7.74 I should get 117.90 but instead get 117.8999999999&lt;br /&gt;&lt;br /&gt;Pretty freakin weird! I assume this has something to do with floating point math and all its weirdness. The fix I found for this was this line:&lt;br /&gt;&lt;br /&gt;total = total.toFixed(2);&lt;br /&gt;&lt;br /&gt;This yeilds the correct value. I bet that I could do this as well to get it correct:&lt;br /&gt;&lt;br /&gt;var total = txtGLItemAmount1.value.toFixed(2) + txtGLItemAmount2.value.toFixed(2);&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114298170257958528?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114298170257958528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114298170257958528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114298170257958528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114298170257958528'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/javascript-rounding-weirdness.html' title='Javascript rounding weirdness'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114261760144100296</id><published>2006-03-17T10:43:00.000-07:00</published><updated>2006-03-17T10:46:41.443-07:00</updated><title type='text'>Locking</title><content type='html'>One thing that you have to worry about in a multithreaded application is the problem of concurrency in that you do not want two seperate threads acessing a value as it is changing. .NET has a method to solve this and it is called locking.&lt;br /&gt;&lt;br /&gt;In c# it is Lock&lt;br /&gt;vb it is SyncLock&lt;br /&gt;&lt;br /&gt;public property GetId() as integer&lt;br /&gt;    get&lt;br /&gt;        syncLock me&lt;br /&gt;            return _id&lt;br /&gt;        end syncLocl&lt;br /&gt;    end get&lt;br /&gt;    set (value as integer)&lt;br /&gt;        syncLock me&lt;br /&gt;            _id = value&lt;br /&gt;        end synclock&lt;br /&gt;    end set&lt;br /&gt;end property&lt;br /&gt;&lt;br /&gt;by calling syncLock me we lock the current object from change. This might not be what is desired so finer grained locking can be done.&lt;br /&gt;&lt;br /&gt;locks work that only one thread can have a lock on an object.&lt;br /&gt;if the object is already locked a calling thread will have to wait until the lock is released.&lt;br /&gt;A single thread is allowed to acquire the same lock on an object unlimited times&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114261760144100296?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114261760144100296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114261760144100296' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114261760144100296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114261760144100296'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/locking.html' title='Locking'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114261738201708484</id><published>2006-03-17T10:37:00.000-07:00</published><updated>2006-03-17T10:43:02.033-07:00</updated><title type='text'>Controls and Threading</title><content type='html'>Controls are not thread safe! you should never try to access a control or modify it from a different thread than the one the control exists on. If you do strange results will happen.&lt;br /&gt;&lt;br /&gt;Fortunately controls have two methods that help us overcome this issue with ease.&lt;br /&gt;control.invoke() to do simple tasks and control.beginInvoke() for longer running tasks that we want to have happen on a background thread.&lt;br /&gt;&lt;br /&gt;Here is a simple example of using beginInvoke()&lt;br /&gt;&lt;br /&gt;dim params() as object = {me, System.EventArgs.Empty}&lt;br /&gt;control.BeginInvoke(new System.EventHandler(Addressof UpdateUi), params)&lt;br /&gt;&lt;br /&gt;private sub UpdateUi(sender as object, e as eventArgs)&lt;br /&gt;{&lt;br /&gt;    lblStatus.text = "Finished"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;as you can see we pass in an array of parameters. In this case the sender and eventargs.&lt;br /&gt;You could also use custom event args to accomplish this:&lt;br /&gt;&lt;br /&gt;MyProgressEvent e = new MyProgressEvent(msg, percentDone);&lt;br /&gt;object[] pList = { this, e };&lt;br /&gt;&lt;br /&gt;private void UpdateUI(object sender, MyProgressEvents e) {&lt;br /&gt;        lblStatus.Text = e.Msg;&lt;br /&gt;        myProgressControl.Value = e.PercentDone;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;Sometimes in our code we will not know if we are on another thread or not. Thankfully again there is a method that lets us know that as well. It is control.InvokeRequired.&lt;br /&gt;It will return false if the calling thread is the thread the control exists on. It will return true when the caller is on another thread.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114261738201708484?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114261738201708484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114261738201708484' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114261738201708484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114261738201708484'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/controls-and-threading.html' title='Controls and Threading'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114166095552119638</id><published>2006-03-06T08:35:00.000-07:00</published><updated>2006-03-06T09:09:15.703-07:00</updated><title type='text'>Objects make your code expandable</title><content type='html'>thats pretty much it. I am a big fan of oop and am working on a project that is not. It now takes me so much longer to do anything and it has a huge impact on the code base and its consumers.&lt;br /&gt;&lt;br /&gt;I have one method like this:&lt;br /&gt;&lt;br /&gt;CreateCashout(clerkId as integer, officeId as integer, cashTotal as double, creditCardTotal as double, debitTotal as double, PaymentIds() as integer)&lt;br /&gt;&lt;br /&gt;This is then validated and passed to the same method signature in the data layer.&lt;br /&gt;&lt;br /&gt;So for one I have a long method signature. Some of these items will be zero (i.e. debit totals for some consumers) so why make them put it in at all.&lt;br /&gt;&lt;br /&gt;Also I would like to see what payments were cash, credit card, and debit but right now I just know all the payments by the paymentId array.&lt;br /&gt;&lt;br /&gt;I would create an object like this:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }.cb2 { color: green; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt; &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt; Cashout&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; mClerkId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; mOfficeId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; mCashTotal &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Double&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; mCreditCardTotal &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Double&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; mDebitTotal &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Double&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    8&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    9&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; mCashPaymentIds() &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   10&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; mCreditCardPaymentIds() &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   11&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; mDebitPaymentIds() &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   12&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   13&lt;/span&gt;     &lt;span class="cb2"&gt;'properties for accessing ClerkId, OfficeId, CashTotal, CreditCardTotal, and DebitTotal&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   14&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   15&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;ReadOnly&lt;/span&gt; &lt;span class="cb1"&gt;Property&lt;/span&gt; PaymentIds() &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   16&lt;/span&gt;         &lt;span class="cb1"&gt;Get&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   17&lt;/span&gt;             &lt;span class="cb2"&gt;'just an example. I have not tested this&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   18&lt;/span&gt;             &lt;span class="cb1"&gt;Dim&lt;/span&gt; allIds(mCashPaymentIds.Length + mCreditCardPaymentIds.Length + mDebitPaymentIds.Length) &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   19&lt;/span&gt;             mCashPaymentIds.CopyTo(allIds, 0)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   20&lt;/span&gt;             mCreditCardPaymentIds.CopyTo(allIds, mCashPaymentIds.Length)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   21&lt;/span&gt;             mDebitPaymentIds.CopyTo(allIds, mCashPaymentIds.Length + mCreditCardPaymentIds.Length)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   22&lt;/span&gt;             &lt;span class="cb1"&gt;Return&lt;/span&gt; allIds&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   23&lt;/span&gt;         &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Get&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   24&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Property&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   25&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   26&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt;(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; clerkId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; officeId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; cashTotal &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Double&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; creditCardTotal &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Double&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; debitTotal &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Double&lt;/span&gt;)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   27&lt;/span&gt;         &lt;span class="cb1"&gt;Me&lt;/span&gt;.ClerkId = clerkId&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   28&lt;/span&gt;         &lt;span class="cb1"&gt;Me&lt;/span&gt;.OfficeId = officeId&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   29&lt;/span&gt;         &lt;span class="cb1"&gt;Me&lt;/span&gt;.CashTotal = cashTotal&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   30&lt;/span&gt;         &lt;span class="cb1"&gt;Me&lt;/span&gt;.CreditCardTotal = creditCardTotal&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   31&lt;/span&gt;         &lt;span class="cb1"&gt;Me&lt;/span&gt;.DebitTotal = debitTotal&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   32&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   33&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   34&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt;(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; clerkId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; officeId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   35&lt;/span&gt;         &lt;span class="cb1"&gt;Me&lt;/span&gt;.ClerkId = clerkId&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   36&lt;/span&gt;         &lt;span class="cb1"&gt;Me&lt;/span&gt;.OfficeId = officeId&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   37&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   38&lt;/span&gt; &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;And the implementation for just creating a cash cashout would now look like this:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt;     &lt;span class="cb1"&gt;Dim&lt;/span&gt; cashout &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; Cashout(clerkId, officeId)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt;     cashout.cashTotal = 30.00&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;     cashout.CashPaymentIds = cashPaymentIds&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;     CreateCashout(cashout)&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;Notice how I now enforced that at least the clerkId and OfficeId are mandatory by having it in both New constructors.&lt;br /&gt;&lt;br /&gt;Also note that in the new constructor that I assign the parameters to properties and not to the fields. i.e. I assigne cashTotals to me.CashTotals instead of mCashTotals&lt;br /&gt;&lt;br /&gt;The reason for this is that there is now a central point to validate all data if need by. i.e. lets say that CashTotals can not be negative we would put the check in the property and be done with it. If we directly assigned it to mCashoutId in the new constructor we would have to check once in the new constructor and once in the property as there are now two ways to set the value of mCashTotals.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114166095552119638?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114166095552119638/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114166095552119638' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114166095552119638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114166095552119638'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/objects-make-your-code-expandable.html' title='Objects make your code expandable'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114149988327411988</id><published>2006-03-04T12:12:00.000-07:00</published><updated>2006-03-04T12:22:52.936-07:00</updated><title type='text'>SQL Administration</title><content type='html'>I run a small hosting provider and one of my issues is backing up SQL databases. Everytime I create a database I have to create a script to back them up. Here is a handy script that I found and modified a bit that will backup all databases to a specified folder. It also keeps a retention history for a user defineable number of days&lt;br /&gt;&lt;br /&gt;here is a sample usage:&lt;br /&gt;isp_FullBackup_UserDBs 'c:\backups', 10&lt;br /&gt;&lt;br /&gt;this will backup all user databases (note it wil not backup the master database) and keep a history of 10 days.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------------------------------------------&lt;br /&gt;-- OBJECT NAME            : isp_FullBackup_UserDBs&lt;br /&gt;--&lt;br /&gt;-- AUTHOR               : Tara Duggan&lt;br /&gt;-- DATE            : December 18, 2003&lt;br /&gt;--&lt;br /&gt;-- INPUTS        : @Path - location of the backups&lt;br /&gt;                          @HistoryDays - Number of days back to keep&lt;br /&gt;&lt;br /&gt;-- OUTPUTS        : None&lt;br /&gt;-- DEPENDENCIES            : None&lt;br /&gt;--&lt;br /&gt;-- DESCRIPTION            : This stored procedure performs a full backup on all of the user databases&lt;br /&gt;--&lt;br /&gt;-- EXAMPLES (optional)  : EXEC isp_FullBackup_UserDBs @Path = 'C:\MSSQL\Backup\', @HistoryDays=14&lt;br /&gt;--&lt;br /&gt;-- MODIFICATION HISTORY :&lt;br /&gt;-- Jan 3, 2005: David Woods - Added the @HistoryDays filter to allow a user specified time period of backups&lt;br /&gt;-- Feb 2, 2005: David Woods - Fixed a bug that would not backup databases with dashes ('-') in the name.&lt;br /&gt;&lt;br /&gt;----------------------------------------------------------------------------------------------------&lt;br /&gt;--&lt;br /&gt;----------------------------------------------------------------------------------------------------&lt;br /&gt;CREATE    PROC isp_FullBackup_UserDBs&lt;br /&gt;@Path VARCHAR(100),&lt;br /&gt;@HistoryDays int --number of days to hold the database&lt;br /&gt;AS&lt;br /&gt;&lt;br /&gt;SET NOCOUNT ON&lt;br /&gt;&lt;br /&gt;DECLARE @Now CHAR(14) -- current date in the form of yyyymmddhhmmss&lt;br /&gt;DECLARE @DBName SYSNAME -- stores the database name that is currently being processed&lt;br /&gt;DECLARE @SQL VARCHAR(7000) -- stores the dynamically created xp_backup_database command&lt;br /&gt;DECLARE @cmd SYSNAME -- stores the dynamically created DOS command&lt;br /&gt;DECLARE @Result INT -- stores the result of the dir DOS command&lt;br /&gt;DECLARE @RowCnt INT -- stores @@ROWCOUNT&lt;br /&gt;&lt;br /&gt;--make sure our path has a trailing slash otherwise we will have a mess of prefixed directories&lt;br /&gt;if SUBSTRING(@path, len(@path), 1) != '\'&lt;br /&gt;Set @Path = @Path + '\'&lt;br /&gt;&lt;br /&gt;-- Get the list of the databases to be backed up, does not include master, model, msdb, tempdb, Northwind, or pubs&lt;br /&gt;SELECT name&lt;br /&gt;INTO #WhichDatabase&lt;br /&gt;FROM master.dbo.sysdatabases&lt;br /&gt;WHERE name NOT IN ('master', 'model', 'msdb', 'pubs', 'tempdb', 'Northwind')&lt;br /&gt;ORDER BY name&lt;br /&gt;&lt;br /&gt;-- Get the database to be backed up&lt;br /&gt;SELECT TOP 1 @DBName = name&lt;br /&gt;FROM #WhichDatabase&lt;br /&gt;&lt;br /&gt;SET @RowCnt = @@ROWCOUNT&lt;br /&gt;&lt;br /&gt;-- Iterate throught the temp table until no more databases need to be backed up&lt;br /&gt;WHILE @RowCnt &lt;&gt; 0&lt;br /&gt;BEGIN&lt;br /&gt;&lt;br /&gt;-- Get the current date using style 120, remove all dashes, spaces, and colons&lt;br /&gt;SELECT @Now = REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(50), GETDATE(), 120), '-', ''), ' ', ''), ':', '')&lt;br /&gt;&lt;br /&gt;-- Build the dir command that will check to see if the directory exists&lt;br /&gt;SELECT @cmd = 'dir ' + @Path + @DBName&lt;br /&gt;&lt;br /&gt;-- Run the dir command, put output of xp_cmdshell into @result&lt;br /&gt;EXEC @result = master.dbo.xp_cmdshell @cmd&lt;br /&gt;&lt;br /&gt;-- If the directory does not exist, we must create it&lt;br /&gt;IF @result &lt;&gt; 0&lt;br /&gt;BEGIN&lt;br /&gt;&lt;br /&gt;    -- Build the mkdir command   &lt;br /&gt;    SELECT @cmd = 'mkdir ' + @Path + @DBName&lt;br /&gt;&lt;br /&gt;    -- Create the directory&lt;br /&gt;    EXEC master.dbo.xp_cmdshell @cmd, NO_OUTPUT&lt;br /&gt;&lt;br /&gt;END&lt;br /&gt;-- The directory exists, so let's delete files older than two days&lt;br /&gt;ELSE&lt;br /&gt;BEGIN&lt;br /&gt;&lt;br /&gt;    -- Stores the name of the file to be deleted&lt;br /&gt;    DECLARE @WhichFile VARCHAR(1000)&lt;br /&gt;&lt;br /&gt;    CREATE TABLE #DeleteOldFiles&lt;br /&gt;    (&lt;br /&gt;    DirInfo VARCHAR(7000)&lt;br /&gt;    )&lt;br /&gt;&lt;br /&gt;    -- Build the command that will list out all of the files in a directory&lt;br /&gt;    SELECT @cmd = 'dir ' + @Path + @DBName + ' /OD'&lt;br /&gt;&lt;br /&gt;    -- Run the dir command and put the results into a temp table&lt;br /&gt;    INSERT INTO #DeleteOldFiles&lt;br /&gt;    EXEC master.dbo.xp_cmdshell @cmd&lt;br /&gt;&lt;br /&gt;    -- Delete all rows from the temp table except the ones that correspond to the files to be deleted&lt;br /&gt;    DELETE&lt;br /&gt;    FROM #DeleteOldFiles&lt;br /&gt;    WHERE ISDATE(SUBSTRING(DirInfo, 1, 10)) = 0 OR DirInfo LIKE '%&amp;lt;dir&amp;gt;%' OR SUBSTRING(DirInfo, 1, 10) &gt;= GETDATE() - @HistoryDays&lt;br /&gt;&lt;br /&gt;    -- Get the file name portion of the row that corresponds to the file to be deleted&lt;br /&gt;    SELECT TOP 1 @WhichFile = SUBSTRING(DirInfo, LEN(DirInfo) -  PATINDEX('% %', REVERSE(DirInfo)) + 2, LEN(DirInfo))&lt;br /&gt;    FROM #DeleteOldFiles&lt;br /&gt;&lt;br /&gt;    SET @RowCnt = @@ROWCOUNT&lt;br /&gt;&lt;br /&gt;    -- Interate through the temp table until there are no more files to delete&lt;br /&gt;    WHILE @RowCnt &lt;&gt; 0&lt;br /&gt;    BEGIN&lt;br /&gt;&lt;br /&gt;        -- Build the del command&lt;br /&gt;        SELECT @cmd = 'del ' + @Path + + @DBName + '\' + @WhichFile + ' /Q /F'&lt;br /&gt;   &lt;br /&gt;        -- Delete the file&lt;br /&gt;        EXEC master.dbo.xp_cmdshell @cmd, NO_OUTPUT&lt;br /&gt;   &lt;br /&gt;        -- To move to the next file, the current file name needs to be deleted from the temp table&lt;br /&gt;        DELETE&lt;br /&gt;        FROM #DeleteOldFiles&lt;br /&gt;        WHERE SUBSTRING(DirInfo, LEN(DirInfo) -  PATINDEX('% %', REVERSE(DirInfo)) + 2, LEN(DirInfo))  = @WhichFile&lt;br /&gt;&lt;br /&gt;        -- Get the file name portion of the row that corresponds to the file to be deleted&lt;br /&gt;        SELECT TOP 1 @WhichFile = SUBSTRING(DirInfo, LEN(DirInfo) -  PATINDEX('% %', REVERSE(DirInfo)) + 2, LEN(DirInfo))&lt;br /&gt;        FROM #DeleteOldFiles&lt;br /&gt;&lt;br /&gt;        SET @RowCnt = @@ROWCOUNT&lt;br /&gt;&lt;br /&gt;    END&lt;br /&gt;&lt;br /&gt;    DROP TABLE #DeleteOldFiles&lt;br /&gt;&lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;-- Build the xp_backup_database command dynamically&lt;br /&gt;SELECT @SQL = ''&lt;br /&gt;SELECT @SQL = @SQL + 'BACKUP DATABASE [' + @DBName + ']' + CHAR(10)&lt;br /&gt;SELECT @SQL = @SQL + 'TO DISK  = ''' + @Path + @DBName + '\' + @DBName + '_' + @Now + '.BAK''' + CHAR(10)&lt;br /&gt;SELECT @SQL = @SQL + 'WITH INIT ' + CHAR(10)&lt;br /&gt;print @SQL&lt;br /&gt;-- Backup the database using xp_backup_database&lt;br /&gt; EXEC (@SQL)&lt;br /&gt;&lt;br /&gt;-- To move onto the next database, the current database name needs to be deleted from the temp table&lt;br /&gt;DELETE&lt;br /&gt;FROM #WhichDatabase&lt;br /&gt;WHERE name = @DBName&lt;br /&gt;&lt;br /&gt;-- Get the database to be backed up&lt;br /&gt;SELECT TOP 1 @DBName = name&lt;br /&gt;FROM #WhichDatabase&lt;br /&gt;&lt;br /&gt;SET @RowCnt = @@ROWCOUNT&lt;br /&gt;&lt;br /&gt;-- Let the system rest for 5 seconds before starting on the next backup&lt;br /&gt;WAITFOR DELAY '00:00:05'&lt;br /&gt;&lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;DROP TABLE #WhichDatabase&lt;br /&gt;&lt;br /&gt;SET NOCOUNT OFF&lt;br /&gt;&lt;br /&gt;RETURN&lt;br /&gt;&lt;br /&gt;GO&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114149988327411988?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114149988327411988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114149988327411988' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114149988327411988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114149988327411988'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/sql-administration.html' title='SQL Administration'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114145019481281806</id><published>2006-03-03T22:22:00.000-07:00</published><updated>2006-03-03T22:29:54.843-07:00</updated><title type='text'>Security Rant</title><content type='html'>Just a quick note on security while it is in my head&lt;br /&gt;&lt;br /&gt;1. Use an accept list instead of a deny list.&lt;br /&gt;    i.e. use a regular expression that matches [A-Za-z0-9]&lt;br /&gt;    vs. ![/*.()&lt;&gt;\......]&lt;br /&gt;&lt;br /&gt;   if you miss one character then your validation is useless. The first validation allows only alphanumeric characters. All else are excluded by the rule.&lt;br /&gt;&lt;br /&gt;Microsoft had this issue with IIS 5 (I beleive) in that people were exploiting it by using the urlencoded values to do directory transversal i.e. www.victim.com/%2c%2c/%2c%2c/%2c%2c/c:\windows\system32\command\cmd.exe&lt;br /&gt;(now that is from memory so don't shoot me)&lt;br /&gt;&lt;br /&gt;If the processor only accepted .. instead of %2c things would have been good&lt;br /&gt;&lt;br /&gt;(note that having %2c is valid so it should have been decoded to a . before it was validated instead of after but that would ruin my example)&lt;br /&gt;&lt;br /&gt;2. Fail closed!&lt;br /&gt;I can not stress this enough. If something goes wrong... shut down! fail! throw a billion exceptions.&lt;br /&gt;&lt;br /&gt;My best example is a firewall. If an unexpected action occured in the firewall what should be done:&lt;br /&gt;       1. Crash and leave all ports open&lt;br /&gt;       2. Crash and close all ports cutting off any legitimate services&lt;br /&gt;&lt;br /&gt;Ok one impacts people connecting but it SHOULD! they will tell you and then you know there is an issue and you can fix it. By failing open in this case you might not know for months that your firewall is not working as no one has complained.&lt;br /&gt;&lt;br /&gt;&lt;/rant&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114145019481281806?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114145019481281806/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114145019481281806' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114145019481281806'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114145019481281806'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/security-rant.html' title='Security Rant'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114133857779237764</id><published>2006-03-02T15:24:00.000-07:00</published><updated>2006-03-02T15:29:37.816-07:00</updated><title type='text'>Throwing Exceptions Part II</title><content type='html'>Sometimes you need to change an exceptions type (usually to a custom exception type) but still want to maintain stacktrace information (read about this issue in part1). Well it is really easy just look at this example&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }.cb2 { color: green; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; Layer2()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;         &lt;span class="cb1"&gt;Throw&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; NotImplementedException&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; LogError(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; ex &lt;span class="cb1"&gt;As&lt;/span&gt; Exception)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt;         &lt;span class="cb2"&gt;'TODO: log the error&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    8&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    9&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   10&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; Layer1()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   11&lt;/span&gt;         &lt;span class="cb1"&gt;Try&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   12&lt;/span&gt;             Layer2()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   13&lt;/span&gt;         &lt;span class="cb1"&gt;Catch&lt;/span&gt; ex &lt;span class="cb1"&gt;As&lt;/span&gt; Exception&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   14&lt;/span&gt;             &lt;span class="cb1"&gt;Throw&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; CustomException("Layer1 error", ex)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   15&lt;/span&gt;         &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Try&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   16&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   17&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   18&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; Button1_Click(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; sender &lt;span class="cb1"&gt;As&lt;/span&gt; System.Object, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; e &lt;span class="cb1"&gt;As&lt;/span&gt; System.EventArgs) &lt;span class="cb1"&gt;Handles&lt;/span&gt; Button1.Click&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   19&lt;/span&gt;         &lt;span class="cb1"&gt;Try&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   20&lt;/span&gt;             Layer1()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   21&lt;/span&gt;         &lt;span class="cb1"&gt;Catch&lt;/span&gt; ex &lt;span class="cb1"&gt;As&lt;/span&gt; Exception&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   22&lt;/span&gt;             LogError(ex)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   23&lt;/span&gt;             &lt;span class="cb1"&gt;Throw&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   24&lt;/span&gt;         &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Try&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   25&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;/div&gt; &lt;br /&gt;By throwing a new exception and adding the caught exception as the inner exception we maintain the stacktrace information.&lt;br /&gt;&lt;br /&gt;FYI my stack output looks like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: times new roman;font-size:85%;" &gt;System.Exception: Layer1 error ---&gt; System.NotImplementedException: The method or operation is not implemented.&lt;br /&gt;   at WindowsApplication1.Form1.Layer2() in C:\...\Form1.vb:line 3&lt;br /&gt;   at WindowsApplication1.Form1.Layer1() in C:\...\Form1.vb:line 12&lt;br /&gt;   --- End of inner exception stack trace ---&lt;br /&gt;   at WindowsApplication1.Form1.Layer1() in C:\..\Form1.vb:line 14&lt;br /&gt;   at WindowsApplication1.Form1.Button1_Click(Object sender, EventArgs e) in C:\..\Form1.vb:line 20&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;you can see that the inner exception has all the trace information down to where the original exception occured but the outer exception shows only that at Layer1() did an exception occur.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114133857779237764?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114133857779237764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114133857779237764' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114133857779237764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114133857779237764'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/throwing-exceptions-part-ii.html' title='Throwing Exceptions Part II'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114133758580544432</id><published>2006-03-02T15:01:00.000-07:00</published><updated>2006-03-02T15:13:05.823-07:00</updated><title type='text'>Throwing Exceptions</title><content type='html'>Don't do this:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }.cb2 { color: green; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt;  &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; DoTask()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt;         &lt;span class="cb1"&gt;Throw&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; NotImplementedException&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; LogError(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; ex &lt;span class="cb1"&gt;As&lt;/span&gt; Exception)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt;         &lt;span class="cb2"&gt;'TODO: log the error&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    8&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    9&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; Button1_Click(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; sender &lt;span class="cb1"&gt;As&lt;/span&gt; System.Object, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; e &lt;span class="cb1"&gt;As&lt;/span&gt; System.EventArgs) &lt;span class="cb1"&gt;Handles&lt;/span&gt; Button1.Click&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   10&lt;/span&gt;         &lt;span class="cb1"&gt;Try&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   11&lt;/span&gt;             DoTask()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   12&lt;/span&gt;         &lt;span class="cb1"&gt;Catch&lt;/span&gt; ex &lt;span class="cb1"&gt;As&lt;/span&gt; Exception&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   13&lt;/span&gt;             LogError(ex)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   14&lt;/span&gt;             &lt;span class="cb1"&gt;Throw&lt;/span&gt; ex&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   15&lt;/span&gt;         &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Try&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   16&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Do this:&lt;br /&gt;&lt;br /&gt;The reason for this is calling throw ex wipes out the stack trace&lt;br /&gt;&lt;br /&gt;The output of the first example using throw ex would be:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: times new roman;"&gt;Unhandled Exception: System.NotImplementedException: The method or operation is not implemented.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: times new roman;"&gt;   at WindowsApplication1.Form1.Button1_Click(Object sender, EventArgs e) in C:\...\Form1.vb:line 70&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Whereas with just using throw:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: times new roman;font-size:85%;" &gt;Unhandled Exception: System.NotImplementedException: The method or operation is not implemented.&lt;br /&gt;   at WindowsApplication1.Form1.DoTask() in C:\...\Form1.vb:line 58&lt;br /&gt;   at WindowsApplication1.Form1.Button1_Click(Object sender, EventArgs e) in C:\...\Form1.vb:line 70&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;By using Throw ex it looks like the exception occured in the method that throws it. By using Throw you can perserve all of the stack trace information and easily see where the error came from.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114133758580544432?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114133758580544432/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114133758580544432' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114133758580544432'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114133758580544432'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/03/throwing-exceptions.html' title='Throwing Exceptions'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114116515058963943</id><published>2006-02-28T15:16:00.000-07:00</published><updated>2006-02-28T15:19:10.590-07:00</updated><title type='text'>The sheer time involved boggles me</title><content type='html'>Check this out: &lt;a href="http://preview.local.live.com/"&gt;http://preview.local.live.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;basically allows you to drive down streets in Seattle or San Fran.&lt;br /&gt;&lt;br /&gt;What really amazed me was turning to the side and seeing a picture of a store front. I have no idea how all of these pictures could have been taken and assembled.&lt;br /&gt;&lt;br /&gt;I am waiting for a real time driving simulator now so that I can get around a city before I arrive there (sorry I am a dork).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114116515058963943?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114116515058963943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114116515058963943' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114116515058963943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114116515058963943'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/sheer-time-involved-boggles-me.html' title='The sheer time involved boggles me'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114105602303037384</id><published>2006-02-27T08:59:00.000-07:00</published><updated>2006-02-27T09:00:23.046-07:00</updated><title type='text'>Code inventor or serial killer</title><content type='html'>Take this &lt;a href="http://www.malevole.com/mv/misc/killerquiz/"&gt;quiz&lt;/a&gt; to see if you can spot the code inventor or the serial killer. I got 9/10 which is pretty freaky.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114105602303037384?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114105602303037384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114105602303037384' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114105602303037384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114105602303037384'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/code-inventor-or-serial-killer.html' title='Code inventor or serial killer'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114081391598096312</id><published>2006-02-24T13:43:00.000-07:00</published><updated>2006-02-24T13:45:15.996-07:00</updated><title type='text'>Side by Side versioning is not so with COM+</title><content type='html'>Today I discovered that when you try to install a com+ (or enterprise service if you want) componenet written in 1.1 of the framework on a system that has 2.0 also installed that you can not install some componenets. I have no idea why or how to fix it besides uninstalling 2.0 then installing your componenet. Then reinstall 2.0 after if you need it.&lt;br /&gt;&lt;br /&gt;...weird!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114081391598096312?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114081391598096312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114081391598096312' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114081391598096312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114081391598096312'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/side-by-side-versioning-is-not-so-with.html' title='Side by Side versioning is not so with COM+'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114079951552446914</id><published>2006-02-24T09:31:00.000-07:00</published><updated>2006-02-24T09:45:15.586-07:00</updated><title type='text'>Unit testing and the database</title><content type='html'>I have been playing with unit testing for over a year now and really see the value in it. Most of the time you build your tests along with (or before in the case of test driven development) your code. But I have even found it valuable to write tests for code I have already written in the past if I am going to have to make a change. I usually only write a test for the method I am about to change, make my change and then see if my test still passes.&lt;br /&gt;&lt;br /&gt;One of the things that I hate is how many articles recommend to mock the database so that no database calls are made. The reason for this is that database interaction is a performance killer. Second of all it loads the database with tons of repeated test data (unless you perform a cleanup in your test case that is).&lt;br /&gt;&lt;br /&gt;I feel that it is invaluable to have your tests hit the database. I have had cases where all of the business rules pass but when it hits the database an exception is thrown. If I had mocked the database I would not know about this. Granted it is slow to do it this way but I would rather be slow than buggy.&lt;br /&gt;&lt;br /&gt;As far as loading the database with repeated test data there are a couple of ways around it. The first is to have every test clean its footprint up which is a big pain. The second way is to enlist the test in a distributed transaction, running the test, and then rolling back the transaction. The way I do this is have a base class that all of my tests inherit from and then have the enlist / rollback in the setup and teardown methods respectively. Here is my standard TestBase class&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }.cb2 { color: green; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt; &lt;span class="cb1"&gt;Imports&lt;/span&gt; NUnit.Framework&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt; &lt;span class="cb1"&gt;Imports&lt;/span&gt; System.EnterpriseServices&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt; &lt;testfixture(),&gt; _&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt; &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt; TestBase&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt;     &lt;setup()&gt; _&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    8&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; Setup()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    9&lt;/span&gt;         &lt;span class="cb2"&gt;' Enter a new transaction without inheriting from ServicedComponent&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   10&lt;/span&gt;         Console.WriteLine("Attempting to enter a transactional context...")&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   11&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; config &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; ServiceConfig&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   12&lt;/span&gt;         config.Transaction = TransactionOption.RequiresNew&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   13&lt;/span&gt;         ServiceDomain.Enter(config)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   14&lt;/span&gt;         Console.WriteLine("Attempt suceeded!")&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   15&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   16&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   17&lt;/span&gt;     &lt;teardown()&gt; _&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   18&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt; Teardown()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   19&lt;/span&gt;         Console.WriteLine("Attempting to Leave transactional context...")&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   20&lt;/span&gt;         &lt;span class="cb1"&gt;If&lt;/span&gt; (ContextUtil.IsInTransaction) &lt;span class="cb1"&gt;Then&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   21&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   22&lt;/span&gt;             ContextUtil.SetAbort()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   23&lt;/span&gt;         &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;If&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   24&lt;/span&gt;         ServiceDomain.Leave()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   25&lt;/span&gt;         Console.WriteLine("Left context!")&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   26&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Sub&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   27&lt;/span&gt; &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   28&lt;/span&gt; &lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The ServiceDomain class is something most people don't know about and is quite handy to ccreate a localized transaction. You can see that it creates a config that requires a new transaction and then calls ServiceDomain.Enter(config). This changes the context of the application to change and participate in a transaction.&lt;br /&gt;&lt;br /&gt;In our tear down we check if we are in a transaction with ContextUtil and then Abort the transaction if we are in it. This will cause all of our interactions with anything that can use DTC to rollback.&lt;br /&gt;&lt;br /&gt;So now you can test your database and not worry about garbage data all over your system. I like this as when I put an applicaiton into production I can run my tests against it and double check that no enviromental errors occured without introducing garbage data.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114079951552446914?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114079951552446914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114079951552446914' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114079951552446914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114079951552446914'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/unit-testing-and-database.html' title='Unit testing and the database'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114066122933038637</id><published>2006-02-22T19:13:00.000-07:00</published><updated>2006-02-22T19:22:43.773-07:00</updated><title type='text'>Marking a method as obsolete</title><content type='html'>I am currently working on an enterprise system that already has several consumers. There are several methods that have been replaced by newer methods and I want the clients to stop consuming the old ones. Unfortunately if I just tell them to use the new ones they wont, and when I release a new version and it breaks they will complain. I found a neat way to deprecate a method&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt; &lt;obsolete("blag",&gt; _&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; oldWay() &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Boolean&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;now whenever a consumer compiles they will get a compiler warning stating that the method has been replaced by method newWay()&lt;br /&gt;&lt;br /&gt;You can also make the compile give a warning instead of an error by using one of the overloads&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt; &lt;obsolete("blag",&gt; _&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;By setting the last parameter to true the compiler will show an error instead of a warning.&lt;br /&gt;&lt;br /&gt;(the first example I posted might actually show an error instead of a warning. I will post more once I experiment with it)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114066122933038637?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114066122933038637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114066122933038637' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114066122933038637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114066122933038637'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/marking-method-as-obsolete.html' title='Marking a method as obsolete'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114062587803583360</id><published>2006-02-22T09:23:00.000-07:00</published><updated>2006-02-22T09:31:18.236-07:00</updated><title type='text'>XSTL / XML and the information bar</title><content type='html'>I am trying out XSLT w/ XML for a project I am doing. Basically the website has a page for each staff memeber with a bio, phone, website, email, photo, etc. The client does not want to pay for a database solution which I would normally do so I decided to try XSLT (If you have no idea what XSLT is you should check out the quick tutorial at www.w3schools.com). Well found a few snags but the one that bugs me the most is the information bar in internet explorer that says it "blocked content that may harm my computer". After some playing and diggiing I found that because it is on my local computer that it is running in the local security zone where it can do damage. If I upload the page I get no warnings because IE puts it into the "Internet Zone" where the active content is blocked by default. To fix this you can place a Mark Of The Web (MOTW) into the xml and xslt document to force a local document to run in the Internet Zone.&lt;br /&gt;&lt;br /&gt;Here is a sample:&lt;br /&gt;my xsl file:&lt;br /&gt;&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;&lt;br /&gt;&lt;!-- saved from url=(0026)http://www.solidhouse.com/ --&gt;&lt;br /&gt;&lt;xsl:stylesheet version="1.0" xsl="http://www.w3.org/1999/XSL/Transform"&gt;&lt;br /&gt;    ...&lt;br /&gt;&lt;/xsl:stylesheet&gt;&lt;br /&gt;&lt;br /&gt;my xml file:&lt;br /&gt;&lt;?xml version="1.0" ?&gt;&lt;br /&gt;&lt;?xml-stylesheet type="text/xsl" href="agent.xsl"?&gt;&lt;br /&gt;&lt;!-- saved from url=(0026)http://www.solidhouse.com/ --&gt;&lt;br /&gt;&lt;agents&gt;&lt;br /&gt;     &lt;agent&gt;&lt;br /&gt;     ....&lt;br /&gt;    &lt;/agent&gt;&lt;br /&gt;&lt;/agents&gt;&lt;br /&gt;&lt;br /&gt;The comment that says "saved from url" is the MOTW. the first part is the string length of the url (26) and the second part is the url of the file.&lt;br /&gt;&lt;br /&gt;As far as I can tell I can put any url in there even if that is not where the file is actually hosted.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114062587803583360?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114062587803583360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114062587803583360' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114062587803583360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114062587803583360'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/xstl-xml-and-information-bar.html' title='XSTL / XML and the information bar'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114056959578462042</id><published>2006-02-21T17:45:00.000-07:00</published><updated>2006-02-21T17:53:15.793-07:00</updated><title type='text'>State management technique</title><content type='html'>One thing that I hate is how most developers access session or cookies like this&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt; &lt;span class="cb1"&gt;Dim&lt;/span&gt; firstname &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt; = Session("firstName")&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;and then 100 times in the application you have the hard code of firstName. About a year ago Tim showed me this very simple and effective way to centralize this. I don't know if there is a name for this technique but I sure love it:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt; &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt; StateManager&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Shared&lt;/span&gt; &lt;span class="cb1"&gt;Property&lt;/span&gt; FirstName() &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;         &lt;span class="cb1"&gt;Get&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;             &lt;span class="cb1"&gt;Return&lt;/span&gt; StateEngine("fistName")&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt;         &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Get&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt;         &lt;span class="cb1"&gt;Set&lt;/span&gt;(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; Value &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt;             StateEngine("FirstName") = Value&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    8&lt;/span&gt;         &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Set&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    9&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Property&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   10&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   11&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; &lt;span class="cb1"&gt;Shared&lt;/span&gt; &lt;span class="cb1"&gt;Property&lt;/span&gt; StateEngine(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; key &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   12&lt;/span&gt;         &lt;span class="cb1"&gt;Get&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   13&lt;/span&gt;             &lt;span class="cb1"&gt;Return&lt;/span&gt; System.Web.HttpContext.Current.Session(key)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   14&lt;/span&gt;         &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Get&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   15&lt;/span&gt;         &lt;span class="cb1"&gt;Set&lt;/span&gt;(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; Value &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Object&lt;/span&gt;)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   16&lt;/span&gt;             System.Web.HttpContext.Current.Session(key) = Value&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   17&lt;/span&gt;         &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Set&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   18&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Property&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   19&lt;/span&gt; &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;now whenever you need to get/set something from state all you have to do is:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt; &lt;span class="cb1"&gt;Dim&lt;/span&gt; firstname &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt; = StateManager.FirstName&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This also alows you to change your state management solution very quickly. If you wanted to move away from session to cookies you would only have to change the implementation in the StateEngine method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114056959578462042?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114056959578462042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114056959578462042' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114056959578462042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114056959578462042'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/state-management-technique.html' title='State management technique'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114056872945818428</id><published>2006-02-21T17:19:00.000-07:00</published><updated>2006-02-21T17:38:49.506-07:00</updated><title type='text'>Patterns: Gateway Pattern</title><content type='html'>One of my favorite patterns is the gateway pattern. Basically it is setting up one class that all requests for a certain action run through. The time I use this the most often is when accessing an external service.&lt;br /&gt;&lt;br /&gt;For example lets say that I use an external service multiple times in an application (in this case I am accessing over a webservice but it could be com, remoting, a database, almost anything)&lt;br /&gt;&lt;br /&gt;In my example I have an external web service that I use to find the customers ID via a phone number. &lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt; &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt; Payment&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; CreatePayment(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; customerPhoneNumber &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; amount &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Decimal&lt;/span&gt;)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; wsPerson &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; com.example.Person&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; personId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt; = wsPerson.GetId(customerPhoneNumber)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; paymentId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt; = Data.CreatePayment(personId, amount)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    8&lt;/span&gt;         &lt;span class="cb1"&gt;Return&lt;/span&gt; paymentId&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    9&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   10&lt;/span&gt; &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   12&lt;/span&gt; &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt; Refund&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   13&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; CreateRefund(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; customerPhoneNumber &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; amount &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Decimal&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; paymentId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;) &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   14&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; wsPerson &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; com.example.Person&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   15&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; personId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt; = wsPerson.GetId(customerPhoneNumber)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   16&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; refundId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt; = Data.CreateRefund(personId, paymentId, amount)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   17&lt;/span&gt;         &lt;span class="cb1"&gt;Return&lt;/span&gt; refundId&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   18&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   19&lt;/span&gt; &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;Now if we ever need to change the service we are using or how it is implemented (i.e. the web service gets changed to remoting or the method to get a person changes) we need to change it all over our application. So to fix this we create a gateway class that pipes all calls to the remote service through it:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt; &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt; PersonGateway&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Shared&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; GetPersonId(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; customerPhoneNumber &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;) &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; wsPerson &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; com.example.Person&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt;         &lt;span class="cb1"&gt;Return&lt;/span&gt; wsPerson.GetId(customerPhoneNumber)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt; &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;We then change our payment and refund classes to use the new gateway:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   10&lt;/span&gt; &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt; Payment&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   11&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; CreatePayment(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; customerPhoneNumber &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; amount &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Decimal&lt;/span&gt;)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   12&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; personId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt; = PersonGateway.GetPersonId(customerPhoneNumber)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   13&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; paymentId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt; = Data.CreatePayment(personId, amount)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   14&lt;/span&gt;         &lt;span class="cb1"&gt;Return&lt;/span&gt; paymentId&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   15&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   16&lt;/span&gt; &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   17&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   18&lt;/span&gt; &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt; Refund&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   19&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; CreateRefund(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; customerPhoneNumber &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; amount &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Decimal&lt;/span&gt;, &lt;span class="cb1"&gt;ByVal&lt;/span&gt; paymentId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;) &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   20&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; personId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt; = PersonGateway.GetPersonId(customerPhoneNumber)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   21&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; refundId &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt; = Data.CreateRefund(personId, paymentId, amount)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   22&lt;/span&gt;         &lt;span class="cb1"&gt;Return&lt;/span&gt; refundId&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   23&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   24&lt;/span&gt; &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;Now we have all calls to the external service in one place. Now we can make changes easily. For example say that the develpers of the Person web service change the method signature to require you to supply a username and password to call the method to prevent outside applications for getting customers information we only have one place to change it:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt; &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt; PersonGateway&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;     &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Shared&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; GetPersonId(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; customerPhoneNumber &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;) &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; wsPerson &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; com.example.Person&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt;         &lt;span class="cb1"&gt;Return&lt;/span&gt; wsPerson.GetId(customerPhoneNumber, "Kudos", "QWERTY")&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt; &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Class&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;This also could allow us a central point to validate the customerPhoneNumber if we wanted as well. By using this methodology it is also easier to create a dummy webservice for testing purposes that allows the application to be debugged without having to rely on an external webservice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114056872945818428?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114056872945818428/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114056872945818428' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114056872945818428'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114056872945818428'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/patterns-gateway-pattern.html' title='Patterns: Gateway Pattern'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114055108107790552</id><published>2006-02-21T12:33:00.000-07:00</published><updated>2006-02-24T10:02:08.300-07:00</updated><title type='text'>Classifying Programmers</title><content type='html'>I was recently asked in an interview how I classify programmers. I found it interesting as there is no set classification of programmers. Here is what I came up with:&lt;br /&gt;&lt;br /&gt;Junior Programmer&lt;br /&gt;-Programmer has difficulties with the language itself (e.g. declaring objects, using properties, sizing of arrays)&lt;br /&gt;-Programmer is not familiar with a lot of the builtin functions/objects in the language (e.g.&lt;br /&gt;-Programmer is not comfterable / aware of OOP.&lt;br /&gt;-Programmer usually has no understanding of interfaces&lt;br /&gt;-Programmer usually can not forsee how to implement a solution and needs to be instructed on the steps to take to acheive the end result.&lt;br /&gt;&lt;br /&gt;Intermediate Programmer&lt;br /&gt;-Programmer is comfterable with the programming language&lt;br /&gt;-Programmer is not familiar with more advanced items of the language (e.g. threading, remoting, com)&lt;br /&gt;-Programmer is fairly familiar with object orientated programming concepts and is comfterable in using them but still runs into problems with some aspects of it&lt;br /&gt;-Programmer knows how to implement interfaces but sees no reason to create them for their own code.&lt;br /&gt;-Programmer runs into problems that they could not forsee which might require backtracking of code / workarounds.&lt;br /&gt;&lt;br /&gt;Senior Programmer&lt;br /&gt;-Programmer is proficient in the programming language&lt;br /&gt;-Programmer has a good understanding of OOP, threading, async programming, and can pick up any new technology (e.g. remoting) and learn it quickly by building on knowledge of similar technologies / underlying principals&lt;br /&gt;-Programmer should be capable of forseeing the strengths / weaknesses of taking a certain route.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Well that is all that I have come up with so far. Please comment on this and let me know your opinion!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-114055108107790552?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114055108107790552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114055108107790552' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114055108107790552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114055108107790552'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/classifying-programmers.html' title='Classifying Programmers'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113708356760700688</id><published>2006-02-20T09:04:00.000-07:00</published><updated>2006-02-20T17:15:31.330-07:00</updated><title type='text'>Design Patterns: Factory Pattern</title><content type='html'>I have always heard of the factory pattern and it is one of the more common patterns out there. I just never really knew why / when to use it until recently. There are serveral compelling reasons to use the factory pattern.&lt;br /&gt;&lt;br /&gt;What is a factory?&lt;br /&gt;Simply put factories are classes / methods that build objects. Here is a simple example of a factory that creates a car:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 255);font-family:arial;font-size:85%;"  &gt;public function CreateCar(color as string, model as string, year as integer, isHatchback as boolean) as Vehicle&lt;br /&gt;dim car as new Vehicle()&lt;br /&gt;car.color=color&lt;br /&gt;car.model=model&lt;br /&gt;car.year=year&lt;br /&gt;&lt;br /&gt;if isHatchback then&lt;br /&gt;car.NumberOfDoors = 3&lt;br /&gt;else&lt;br /&gt;car.NumberOfDoors = 4&lt;br /&gt;end if&lt;br /&gt;&lt;br /&gt;return car&lt;br /&gt;end function&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;we could then add another factory that creates a truck&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 255);font-family:arial;font-size:85%;"  &gt;public function CreateTruck(color as string, model as string, year as integer) as Vehicle&lt;br /&gt;dim truck as new Vehicle()&lt;br /&gt;truck.color=color&lt;br /&gt;truck.model=model&lt;br /&gt;truck.year=year&lt;br /&gt;truck.numberOfDoors = 2&lt;br /&gt;return truck&lt;br /&gt;end function&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What I like to do is put the factory methods directly into the object I am creating (in this case Vehicle). I then make the constructor private to force users to call the Create____ method. i.e.:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 102, 255);font-family:arial;font-size:85%;"  &gt;public class Vehicle()&lt;br /&gt;dim color as string&lt;br /&gt;dim model as string&lt;br /&gt;dim year as integer&lt;br /&gt;dim numberOfDoors as integer&lt;br /&gt;dim fuel as string&lt;br /&gt;&lt;br /&gt;private sub new()&lt;br /&gt;engine = "gas"&lt;br /&gt;end sub&lt;br /&gt;&lt;br /&gt;public shared function CreateCar(color as string, model as string, year as integer, isHatchback as boolean) as Vehicle&lt;br /&gt;dim car as new Vehicle()&lt;br /&gt;car.color=color&lt;br /&gt;car.model=model&lt;br /&gt;car.year=year&lt;br /&gt;&lt;br /&gt;if isHatchback then&lt;br /&gt;car.NumberOfDoors = 3&lt;br /&gt;else&lt;br /&gt;car.NumberOfDoors = 4&lt;br /&gt;end if&lt;br /&gt;&lt;br /&gt;return car&lt;br /&gt;end function&lt;br /&gt;&lt;br /&gt;public shared function CreateTruck(color as string, model as string, year as integer) as Vehicle&lt;br /&gt;dim truck as new Vehicle()&lt;br /&gt;truck.color=color&lt;br /&gt;truck.model=model&lt;br /&gt;truck.year=year&lt;br /&gt;truck.numberOfDoors = 2&lt;br /&gt;return truck&lt;br /&gt;end function&lt;br /&gt;&lt;br /&gt;end class&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Now if you are anything like me you would be thinking why not just use the new constructor in vehicle to do this? The answer is yes we could but no we should not.&lt;br /&gt;&lt;br /&gt;The main reason I use a factory is  clarity. You can only name a constructor "new". which is not very descriptive. If we used the new constructor the signature woud look like this:&lt;br /&gt;public sub new (color as string, model as string, year as integer, isHatchback as boolean)&lt;br /&gt;public sub new (color as string, model as string, year as integer)&lt;br /&gt;&lt;br /&gt;As a developer not familiar with the code I might assume I can create a car by calling the second method only to be supprised that it comes back as a car with 2 doors which is not what I desired. Where as if it was done through the factory method I know just by the name of the method that I should call CreateCar() to create a car and CreateTruck() to create a truck.&lt;br /&gt;&lt;br /&gt;The other place a factory can be usefull is with inheritance chains as the new() constructors on objects do not get inherited but the factory methods will.&lt;br /&gt;&lt;br /&gt;It is quick to see how powerfull this technique can be and where it can be used. Be warned though that most developers expect methods to have a new constructor on objects. This is why it is gennerally a common practice to prefix factory methods with the word Create. i.e. sqlConnection.CreateCommand() returns a command object associated to the command.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113708356760700688?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113708356760700688/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113708356760700688' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113708356760700688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113708356760700688'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/design-patterns-factory-pattern.html' title='Design Patterns: Factory Pattern'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-114003628862548634</id><published>2006-02-15T13:35:00.000-07:00</published><updated>2006-02-15T14:16:45.426-07:00</updated><title type='text'>Getting the current Method</title><content type='html'>I have an application that logs information when each method runs:&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }.cb2 { color: green; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt;  &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; GetRefundsByID(&lt;span class="cb1"&gt;ByVal&lt;/span&gt; id &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;Integer&lt;/span&gt;)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt;         &lt;span class="cb2"&gt;'implementation&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;         LogMessage(&lt;span class="cb1"&gt;String&lt;/span&gt;.Format("GetRefundsByID found {0} records", count))&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;I dont really like this as I have now hardcoded the name of the function into each method which really sucks when I rename a method.&lt;br /&gt;&lt;br /&gt;I managed to figure a way to get the current method name via reflection though (note that reflection can adversley affect performance)&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }.cb2 { color: green; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt;     &lt;span class="cb1"&gt;Private&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; GetCurrentMethodName() &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; stackTrace &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; StackTrace &lt;span class="cb2"&gt;'the stack trace&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; stackFrame &lt;span class="cb1"&gt;As&lt;/span&gt; StackFrame &lt;span class="cb2"&gt;'one frame of the stack i.e. the last calling method&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; methodBase &lt;span class="cb1"&gt;As&lt;/span&gt; methodBase &lt;span class="cb2"&gt;'the method info&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt;         stackFrame = stackTrace.GetFrame(1) &lt;span class="cb2"&gt;'get the frame that happened just before this method&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt;         methodBase = stackFrame.GetMethod() &lt;span class="cb2"&gt;'get the method info from that frame&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    8&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    9&lt;/span&gt;         &lt;span class="cb1"&gt;Return&lt;/span&gt; methodBase.Name&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   10&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;Now that code is a little ugly so here it is refactored:&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt;   &lt;span class="cb1"&gt;Public&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; GetcurrentMethodName()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt;         &lt;span class="cb1"&gt;Return&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; StackTrace().GetFrame(1).GetMethod().Name&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;Or if you want to show the parameter signature you can use this:&lt;br /&gt;&lt;style type="text/css"&gt;.cf { font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt; }.cl { margin: 0px; }.cln { color: teal; }.cb1 { color: blue; }&lt;/style&gt;&lt;div class="cf"&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    1&lt;/span&gt;   &lt;span class="cb1"&gt;Private&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt; GetCurrentMethodName() &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;String&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    2&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; methodBase &lt;span class="cb1"&gt;As&lt;/span&gt; System.Reflection.MethodBase&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    3&lt;/span&gt;         &lt;span class="cb1"&gt;Dim&lt;/span&gt; sb &lt;span class="cb1"&gt;As&lt;/span&gt; &lt;span class="cb1"&gt;New&lt;/span&gt; System.Text.StringBuilder&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    4&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    5&lt;/span&gt;         methodBase = &lt;span class="cb1"&gt;New&lt;/span&gt; StackTrace().GetFrame(1).GetMethod()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    6&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    7&lt;/span&gt;         sb.AppendFormat("{0} (", methodBase.Name)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    8&lt;/span&gt;         &lt;span class="cb1"&gt;For&lt;/span&gt; &lt;span class="cb1"&gt;Each&lt;/span&gt; param &lt;span class="cb1"&gt;As&lt;/span&gt; System.Reflection.ParameterInfo &lt;span class="cb1"&gt;In&lt;/span&gt; methodBase.GetParameters()&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;    9&lt;/span&gt;             sb.AppendFormat(param.Name &amp; " as " &amp;amp; param.ParameterType().Name)&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   10&lt;/span&gt;         &lt;span class="cb1"&gt;Next&lt;/span&gt;&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   11&lt;/span&gt;         sb.AppendFormat(")")&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   12&lt;/span&gt; &lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   13&lt;/span&gt;         &lt;span class="cb1"&gt;Return&lt;/span&gt; sb.ToString&lt;/p&gt;&lt;p class="cl"&gt;&lt;span class="cln"&gt;   14&lt;/span&gt;     &lt;span class="cb1"&gt;End&lt;/span&gt; &lt;span class="cb1"&gt;Function&lt;/span&gt;&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/19004283-114003628862548634?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/114003628862548634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=114003628862548634' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114003628862548634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/114003628862548634'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/02/getting-current-method.html' title='Getting the current Method'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113832863611353053</id><published>2006-01-26T19:15:00.000-07:00</published><updated>2006-01-26T19:23:56.126-07:00</updated><title type='text'>Dynamic Order By's</title><content type='html'>Here is cool technique I saw here (http://www.sqlteam.com/item.asp?ItemID=2209)&lt;br /&gt;&lt;br /&gt;Basically I knew of no way to do a dynamic order by / group by without creating dynamic sql i.e.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;b&gt;DECLARE @SortOrder varchar(30)&lt;br /&gt;DECLARE @sql varchar(8000)&lt;br /&gt;SET @SortOrder = 'CompanyName'&lt;br /&gt;&lt;br /&gt;set @sql = 'SELECT CompanyName,&lt;br /&gt;        ContactName,&lt;br /&gt;        ContactTitle&lt;br /&gt;     FROM Customers&lt;br /&gt;      ORDER BY ' + @SortOrder&lt;br /&gt;&lt;br /&gt;exec(@sql)&lt;br /&gt;&lt;/b&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This sucks as SQL can not validate the syntax, the engine can not cache the execution plan, and this could open up a SQL injection attack (I am pretty sure that sql will filter / escape the incomming string though).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Anyways here is the better way to do it:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;b&gt;DECLARE @SortOrder tinyint&lt;br /&gt;SET @SortOrder = 2&lt;br /&gt;&lt;br /&gt;SELECT CompanyName,&lt;br /&gt;     ContactName,&lt;br /&gt;     ContactTitle&lt;br /&gt;FROM Customers&lt;br /&gt;ORDER BY CASE WHEN @SortOrder = 1 THEN CompanyName&lt;br /&gt;            WHEN @SortOrder = 2 THEN ContactName&lt;br /&gt;            ELSE ContactTitle&lt;br /&gt;       END&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Pretty freakin sweet! There is also an interesting item on that site about creating a dynamic where clause by using COALLESCE.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113832863611353053?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113832863611353053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113832863611353053' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113832863611353053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113832863611353053'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/01/dynamic-order-bys.html' title='Dynamic Order By&apos;s'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113769097985951013</id><published>2006-01-19T09:46:00.000-07:00</published><updated>2006-01-19T10:16:19.943-07:00</updated><title type='text'>Why I hate oracle</title><content type='html'>I unfortunately keep running into places that need to migrate oracle or I have had the unfortunate responsibility of teaching it. I absolutely can not stand this product and I have a list why:&lt;br /&gt;&lt;br /&gt;1. Cost. what an expensive POS.&lt;br /&gt;2. useless junk. Oracle ships with tons of utilities that will never need to be used&lt;br /&gt;3. Bloated install. Installes several apache instance / services I don't need&lt;br /&gt;4. GUI = the suck. I have never used such hard management tools&lt;br /&gt;5. no good query tool. The query tools appear to be wrappers around their dos sql utility. Its like microsoft word using dos's edit command for an engine.&lt;br /&gt;6. TNS Names. The only way to connect to a database is to setup a tnsnames.ora file that makes a name map to an ip, port, and service. Pray you dont have a syntax error. Why not just have it so the client can connect to an IP? It makes no sense and is just another step.&lt;br /&gt;7. Roles are sooo confusing. whats a SysOper, SysDba, normal? why not just have a good permissions model&lt;br /&gt;8. Client size. Just to download the client so that I can connect is 550MB. 550MB! Thats MegaBytes! glad I am not on dialup.&lt;br /&gt;9. Support. I tried to email them but they don't have an address on their site. I tried to call them but because I don't have some CID number (or something like that) I can not get through the voice system. I press 0 over and over to get an operator and it just says "Thanks for calling" and hangs up on me.&lt;br /&gt;10. 80's style application. The application takes so long to learn and is so convoluted it reminds me of working on my Apple IIe (may it rest in peace). The GUI looks like a win 3.1 app and the steps required to do anything seem to take forever.&lt;br /&gt;&lt;br /&gt;Now I know a lot of this is due to me not knowing a ton about oracle but software should be intuitive. I have learned the basics of a database in an afternoon but I have been playing with oracle (very rarely but still using it here and there) for the past 3 years and I still have no clue why anyone uses it when there are products out there that are comparable for a fraction of the price.&lt;br /&gt;&lt;br /&gt;My recommendation to oracle is to keep the engine the same but build some tools that make a developers life easy. Make the install for both client and server as minimal as possible and then allow me to choose what I want. Make it affordable. Modernize the application and interface.&lt;br /&gt;&lt;br /&gt;Oh btw Oracle has had a pretty crappy security record. Just now they released 80 patches for Oracle 10 in their quartly patch cycle. YAY! 80 security holes in 3 months!&lt;br /&gt;&lt;br /&gt;My other issue was Oracle 9i. It was originally called Oracle 9i Unbreakable as it was sooo secure no one could hack it. Security Researcher David Litchfield found high risk security holes in the application days after it was touted as "Unbreakable". I could not find a count of security holes in the 9i database but I know it sure was replaced with Oracle 10 pretty quickly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113769097985951013?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113769097985951013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113769097985951013' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113769097985951013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113769097985951013'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/01/why-i-hate-oracle.html' title='Why I hate oracle'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113762461286376909</id><published>2006-01-18T15:31:00.000-07:00</published><updated>2006-01-18T15:50:12.910-07:00</updated><title type='text'>Say screw it to parsing filenames</title><content type='html'>I recently discovered some builtin classes to parse file paths instead of awkward .IndexOf / substring combinations&lt;br /&gt;&lt;br /&gt;dim filename as string = "c:\windows\temp\stuff\myfile.txt"&lt;br /&gt;&lt;br /&gt;the IO.Path has many shared methods that allow parsing and manipulation&lt;br /&gt;&lt;br /&gt;IO.Path.ChangeExtension(filename, "xml")    'c:\windows\temp\stuff\myFile.xml&lt;br /&gt;IO.Path.Combine()                                       'have not played with this one yet&lt;br /&gt;IO.Path.GetDirectoryName(filename)             'c:\windows\temp\stuff&lt;br /&gt;IO.Path.GetExtension(filename)                       '.txt&lt;br /&gt;IO.Path.GetFileName(filename)                'myfile.txt&lt;br /&gt;IO.Path.GetFileNameWithoutExtension(filename)                'myfile&lt;br /&gt;IO.Path.GetFullPath(filename)                  'c:\windows\temp\stuff\myfile.txt&lt;br /&gt;IO.Path.GetFullPath("blah.txt")                'c:\vss\project\bin\blah.txt"&lt;br /&gt;IO.Path.GetPathRoot(filename)                'c:IO.Path.GetTempFileName()                    'c:\temp\tmp260A.tmp   (gauranteed unique file)&lt;br /&gt;IO.Path.GetTempPath()                             'c:\temp\ (gets windows temp dir)&lt;br /&gt;IO.Path.HasExtension(filename)               'True  (false if no file extension)&lt;br /&gt;IO.Path.IsPathRooted(filename)               'True     (path is an absolute or relative. absolute in this case)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I recently used this for a project where I wanted to create the directory for a file if the directory did not exist.&lt;br /&gt;&lt;br /&gt;IO.Directory.CreateDirectory(io.Path.GetDirectoryName("c:\temp\test1\test1\test1\tmp.txt"))&lt;br /&gt;&lt;br /&gt;Note that CreateDirectory will recursively create any missing directories (when I ran this I only had a "c:\temp" directory).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Another handy method is IO.Directory.GetCurrentDirectory() which gets the current working directory of the application&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113762461286376909?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113762461286376909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113762461286376909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113762461286376909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113762461286376909'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/01/say-screw-it-to-parsing-filenames.html' title='Say screw it to parsing filenames'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113751572609668918</id><published>2006-01-17T09:16:00.000-07:00</published><updated>2006-01-17T09:35:26.193-07:00</updated><title type='text'>Custom EventArgs</title><content type='html'>I don't know if there is a name for this pattern or not but I have found that it is quite helpfull. When creating custom events it should only have two parameters. One being the object that raised the event and the other should be an object containing data.&lt;br /&gt;&lt;br /&gt;I like examples so lets start with these two classes:&lt;br /&gt;&lt;br /&gt;public class MyApp&lt;br /&gt;       &lt;br /&gt;       private withEvents eventClass as  MyEventRaiser&lt;br /&gt;&lt;br /&gt;      private sub DoTask()&lt;br /&gt;              eventClass.DoTask()   &lt;br /&gt;      end sub&lt;br /&gt;&lt;br /&gt;       private sub eventClass_MyEvent(arg1 as string, arg2 as integer, arg3 as bool) handles eventClass.MyEvent&lt;br /&gt;&lt;br /&gt;               messagebox.show(arg1)&lt;br /&gt;       end sub&lt;br /&gt;&lt;br /&gt;end class&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class MyEventRaiser&lt;br /&gt;     &lt;br /&gt;      public event MyEvent(arg1 as string, arg2 as integer, arg3 as bool)&lt;br /&gt;&lt;br /&gt;      public sub DoTask()&lt;br /&gt;           RaiseEvent MyEvent("test", 32, true)&lt;br /&gt;      end sub&lt;br /&gt;&lt;br /&gt;end class&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This is fairly cut and dry. When a call to MyEventRaiser.DoTask() is run an event is raised. In this case it is handled by MyClass.eventClass_MyEvent().&lt;br /&gt;&lt;br /&gt;The problem with this setup comes to making changes. In every project there is change. We might run into a case where we need to return another parameter when the event gets raised. We could add it on to the event declaration, the RaiseEvent statement, and every place it is handled.&lt;br /&gt;&lt;br /&gt;If the event is handled in 50 places we have to make 50 changes. Even though it might be that only one of those handlers actually cares about the new parameter.&lt;br /&gt;&lt;br /&gt;To mitigate this issue we create a class that inherits from eventArgs:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class MyEventArgs&lt;br /&gt;      inherits EventArgs&lt;br /&gt;&lt;br /&gt;     private _arg1 as string&lt;br /&gt;     private _arg2 as integer&lt;br /&gt;     private _arg3 as boolean&lt;br /&gt;&lt;br /&gt;    public property Arg1 as string&lt;br /&gt;         get&lt;br /&gt;              return _arg1&lt;br /&gt;         end get&lt;br /&gt;         set (value as string)&lt;br /&gt;               _arg1 = value&lt;br /&gt;         end set&lt;br /&gt;    end property&lt;br /&gt;&lt;br /&gt;    public property Arg2 as integer&lt;br /&gt;         get&lt;br /&gt;              return _arg2&lt;br /&gt;         end get&lt;br /&gt;         set (value as integer)&lt;br /&gt;               _arg2 = value&lt;br /&gt;         end set&lt;br /&gt;    end property&lt;br /&gt;&lt;br /&gt;    public property Arg3 as boolean&lt;br /&gt;         get&lt;br /&gt;              return _arg3&lt;br /&gt;         end get&lt;br /&gt;         set (value as boolean)&lt;br /&gt;               _arg3 = value&lt;br /&gt;         end set&lt;br /&gt;    end property&lt;br /&gt;&lt;br /&gt;     public sub new (arg1 as string, arg2 as integer, arg3 as bool)&lt;br /&gt;                _arg1 = arg1&lt;br /&gt;                _arg2 = arg2&lt;br /&gt;                _arg3 = arg3&lt;br /&gt;     end sub&lt;br /&gt;end class&lt;br /&gt;&lt;br /&gt;So now we have an object that encapsulates all of the data for our event. We then change our&lt;br /&gt;class that declares the event like so:&lt;br /&gt;&lt;br /&gt;public class MyEventRaiser&lt;br /&gt;     &lt;br /&gt;      public event MyEvent(sender as object, e as MyEventArgs)&lt;br /&gt;&lt;br /&gt;      public sub DoTask()&lt;br /&gt;           RaiseEvent MyEvent(me, New MyEventArgs("test", 32, true))&lt;br /&gt;      end sub&lt;br /&gt; end class&lt;br /&gt;&lt;br /&gt;Starting to look familiar? This is what microsoft did for all of its built in events. The sender is always the object that raised the event. This allows the objects that receive the event access to the object that created it.&lt;br /&gt;&lt;br /&gt;Now the only thing left is to change the signature of the methods that handle the method.&lt;br /&gt;&lt;br /&gt;public class MyApp&lt;br /&gt;       &lt;br /&gt;       private withEvents eventClass as  MyEventRaiser&lt;br /&gt;&lt;br /&gt;      private sub DoTask()&lt;br /&gt;              eventClass.DoTask()   &lt;br /&gt;      end sub&lt;br /&gt;&lt;br /&gt;       private sub eventClass_MyEvent(sender as object, e as MyEventArgs) handles eventClass.MyEvent&lt;br /&gt;&lt;br /&gt;               messagebox.show(e.arg1)&lt;br /&gt;       end sub&lt;br /&gt;&lt;br /&gt;end class&lt;br /&gt;&lt;br /&gt;From now on if we need to add a new parameter we simply add it onto the MyEventArgs class.&lt;br /&gt;By doing this we dont need to change 50 method signatures to accept a new parameter that the method never uses.&lt;br /&gt;&lt;br /&gt;Happy Eventing!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113751572609668918?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113751572609668918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113751572609668918' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113751572609668918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113751572609668918'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/01/custom-eventargs.html' title='Custom EventArgs'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113751091884926162</id><published>2006-01-17T08:12:00.000-07:00</published><updated>2006-01-17T08:15:18.866-07:00</updated><title type='text'>Heap vs. Stack</title><content type='html'>I found these three articles really good regarding the heap and stack.&lt;br /&gt;&lt;br /&gt;Part I&lt;br /&gt;&lt;a href="http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx?ArticleID=9adb0e3c-b3f6-40b5-98b5-413b6d348b91&amp;PagePath=/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx"&gt;http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx?ArticleID=9adb0e3c-b3f6-40b5-98b5-413b6d348b91&amp;amp;PagePath=/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Part II&lt;br /&gt;&lt;a href="http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx?ArticleID=c31e9a39-d364-429f-a4fa-0a60444d3add&amp;PagePath=/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx"&gt;http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx?ArticleID=c31e9a39-d364-429f-a4fa-0a60444d3add&amp;amp;PagePath=/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Part III&lt;br /&gt;&lt;a href="http://www.c-sharpcorner.com/UploadFile/rmcochran/chsarp_memory401152006094206AM/chsarp_memory4.aspx?ArticleID=4f58d369-9e0c-4f7a-8a84-5883faade356&amp;PagePath=/UploadFile/rmcochran/chsarp_memory401152006094206AM/chsarp_memory4.aspx"&gt;http://www.c-sharpcorner.com/UploadFile/rmcochran/chsarp_memory401152006094206AM/chsarp_memory4.aspx?ArticleID=4f58d369-9e0c-4f7a-8a84-5883faade356&amp;amp;PagePath=/UploadFile/rmcochran/chsarp_memory401152006094206AM/chsarp_memory4.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113751091884926162?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113751091884926162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113751091884926162' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113751091884926162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113751091884926162'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/01/heap-vs-stack.html' title='Heap vs. Stack'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113744136092378846</id><published>2006-01-16T12:55:00.000-07:00</published><updated>2006-01-16T13:01:54.006-07:00</updated><title type='text'>Delegates in vb.net part III</title><content type='html'>The next item in delegates I want to cover is returning data. In my previous example we called a sub that did a task (writing out a file) but it did not return any data or notify us that we were done. To accomplish this we are going to use a delegate with a callback method.&lt;br /&gt;&lt;br /&gt;Here is the code I am going to start with:&lt;br /&gt;&lt;br /&gt;Private Sub StartTask()&lt;br /&gt;        Dim del As New DoLongTaskDelegate(AddressOf DoLongTask)&lt;br /&gt;        del.BeginInvoke("c:\temp.txt", Nothing, Nothing)&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Private Delegate Function DoLongTaskDelegate(ByVal filename As String) As Integer&lt;br /&gt;&lt;br /&gt;Private Function DoLongTask(ByVal filename As String) As Integer&lt;br /&gt;           'do long task&lt;br /&gt;          Return 537&lt;br /&gt;End Function&lt;br /&gt;&lt;br /&gt;Now in order to capture the returned data we will need a method to be executed when the method completes. This method must accept an IAsyncResult as a parameter&lt;br /&gt;&lt;br /&gt;Private Sub TaskDone(ByVal ar As IAsyncResult)&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;we then change our BeginInvoke call and set the second parameter to be the AddressOf this new method:&lt;br /&gt;&lt;br /&gt;del.BeginInvoke("c:\temp.txt", AddressOf TaskDone, del)&lt;br /&gt;&lt;br /&gt;We set the 4th parameter to be the actuall delegate we created. We need to do this so that when the method completes we have access to the delegated method itself (remember that a delegate is basically a pointer to a methd) so that we can access its return value.&lt;br /&gt;&lt;br /&gt;In the TaskDone method add these two lines:&lt;br /&gt;&lt;br /&gt;Dim del As DoLongTaskDelegate = ar.AsyncState&lt;br /&gt;MessageBox.Show(del.EndInvoke(ar))&lt;br /&gt;&lt;br /&gt;The ar.AsyncState now holds the delegate we passed in when calling BeginInvoke. We then call EndInvoke on the delegate to get the result. I know how confusing this is when you start but after you play with it for a while it starts to make more sense.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113744136092378846?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113744136092378846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113744136092378846' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113744136092378846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113744136092378846'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/01/delegates-in-vbnet-part-iii.html' title='Delegates in vb.net part III'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113743710476168782</id><published>2006-01-16T11:28:00.000-07:00</published><updated>2006-01-16T12:58:21.290-07:00</updated><title type='text'>Delegates in vb.net part II</title><content type='html'>A delegate also has built in methods that allow background execution of the method it points to which is what we are going to use here. Most times I start a task on a background thread I use Thread.Start(). Unfortunately if you have a method that takes parameters you can not use Thread.Start. Instead we will use a delegate which will allow us to pass parameters to a method running on another thread.&lt;br /&gt;&lt;br /&gt;I have a project where I need to write to a file on a background thread. The WriteFile method takes one parameter (the file path).&lt;br /&gt;&lt;br /&gt;public sub WriteFile(byVal outputFile as String)&lt;br /&gt;      //implementation&lt;br /&gt;end sub&lt;br /&gt;&lt;br /&gt;To build a delegate I simply do this:&lt;br /&gt;&lt;br /&gt;private Delegate Sub FileWriteDelegate(ByVal outputFile as String)&lt;br /&gt;&lt;br /&gt;Note that the delegate has the same method signature as the method I am going to call.&lt;br /&gt;&lt;br /&gt;private sub DoTask()&lt;br /&gt;     WriteFile("c:\temp.txt")&lt;br /&gt;end sub&lt;br /&gt;&lt;br /&gt;To run it on a background thread I change the DoTask method to create an instance of the delegate and then call BeginInvoke.&lt;br /&gt;&lt;br /&gt;private sub DoTask()&lt;br /&gt;       Dim x As New FileWriteDelegate(AddressOf WriteFile)&lt;br /&gt;       x.BeginInvoke(outputFile, Nothing, Nothing)&lt;br /&gt;end sub&lt;br /&gt;&lt;br /&gt;You will note that when you call beginInvoke you must specify a string of filename. I have set the other params to nothing. I will cover the other two params of BeginInvoke in my next post. That is pretty much it! I will try to write more on Delegates as I think this is the one feature that most vb.net developers know nothing about or don't know how / when to use them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113743710476168782?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113743710476168782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113743710476168782' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113743710476168782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113743710476168782'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/01/delegates-in-vbnet-part-ii.html' title='Delegates in vb.net part II'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113743572433153414</id><published>2006-01-16T11:10:00.000-07:00</published><updated>2006-01-16T12:55:28.760-07:00</updated><title type='text'>Delegates in vb.net</title><content type='html'>For those of us that are not C# developers we rarely deal with delegates. A delegate is simply a strong typed pointer to a method. C# uses this extensively for wiring of events. VB.NET actually builds the event delegates for us behind the scenes.&lt;br /&gt;&lt;br /&gt;Here is a quick example of a simple delegate:&lt;br /&gt;&lt;br /&gt;Public Delegate Sub TrafficLightChangedEventHandler(ByVal color As String)&lt;br /&gt;&lt;br /&gt;Private Sub TrafficLightChanged(ByVal color As String)&lt;br /&gt;      MsgBox(color)&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Private Sub StartDelegate()&lt;br /&gt;    Dim del As TrafficLightChangedEventHandler&lt;br /&gt;    del = New TrafficLightChangedEventHandler(AddressOf TrafficLightChanged)&lt;br /&gt;    del.Invoke("Red")&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;When startDelegate gets called we create an instance of the Delegate and put in the address of the TrafficLightChanged method which will be called when we run del.invoke("Red"). Note that invoke automatically knew what parameters were required (in this case a color string).&lt;br /&gt;&lt;br /&gt;Delegates can also be used to invoke multiple methods with one invoke call. This is often refered to as a MultiCast Delegate.&lt;br /&gt;&lt;br /&gt;Public Delegate Sub TrafficLightChangedEventHandler(ByVal color As String)&lt;br /&gt;&lt;br /&gt;Private Sub TrafficLightChanged(ByVal color As String)&lt;br /&gt;     MsgBox(color)&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Private Sub TrafficLightChanged2(ByVal color As String)&lt;br /&gt;     MsgBox("2: " &amp; color)&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;Private Sub StartDelegate()&lt;br /&gt;     Dim del As TrafficLightChangedEventHandler&lt;br /&gt;     del = New TrafficLightChangedEventHandler(AddressOf TrafficLightChanged)&lt;br /&gt;     del = TrafficLightChangedEventHandler.Combine(New TrafficLightChangedEventHandler     (AddressOf TrafficLightChanged), New TrafficLightChangedEventHandler(AddressOf      TrafficLightChanged2))&lt;br /&gt;     del.Invoke("Red")&lt;br /&gt;End Sub&lt;br /&gt;&lt;br /&gt;When we call Invoke() the delegate will execute both TrafficLightChanged and TrafficLightChanged2.&lt;br /&gt;&lt;br /&gt;This is exactly how events work in .NET. Raising one event could cause multiple methods to execute that are wired to handle the event.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113743572433153414?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113743572433153414/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113743572433153414' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113743572433153414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113743572433153414'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/01/delegates-in-vbnet.html' title='Delegates in vb.net'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113716625008916039</id><published>2006-01-13T08:27:00.000-07:00</published><updated>2006-01-13T08:30:50.103-07:00</updated><title type='text'>Overlaying an image overtop of another image</title><content type='html'>Recently I was asked to build a website that when a property got sold a little sold sticker appeared in the upper corner of the image. I thought this would be really hard based on my experience with php image manipulation.  With .NET and GDI+ it was so easy. Here it is:&lt;br /&gt;&lt;br /&gt;Dim baseImage As Image&lt;br /&gt;Dim overlayImage As Image&lt;br /&gt;baseImage = Image.FromFile("c:\house.jpg")&lt;br /&gt;overlayImage = Image.FromFile("c:\loginButton.jpg")&lt;br /&gt;&lt;br /&gt;Dim gr As Graphics&lt;br /&gt;gr = Graphics.FromImage(baseImage)&lt;br /&gt;gr.DrawImage(overlayImage, 10, 10)&lt;br /&gt;&lt;br /&gt;Me.PictureBox1.Image = baseImage&lt;br /&gt;&lt;br /&gt;This is  easy to change to load from a stream / save it to a web output stream (baseImage.Save(Response.OutputStream)).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113716625008916039?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113716625008916039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113716625008916039' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113716625008916039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113716625008916039'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2006/01/overlaying-image-overtop-of-another.html' title='Overlaying an image overtop of another image'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113503347735515965</id><published>2005-12-19T16:00:00.000-07:00</published><updated>2005-12-20T09:05:31.320-07:00</updated><title type='text'>SQL Reporting Services: Alternating Item Color</title><content type='html'>To my supprise Reporting services does not seem to have support for an alternating item color when displaying a table (well that I can find at least). &lt;br /&gt;&lt;br /&gt;After some playing I came up with a simple little iif statement.&lt;br /&gt;Simply set the rows Background color in the properties pane to this:&lt;br /&gt;=iif(RowNumber(Nothing) Mod 2, "LightGrey", "White")&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113503347735515965?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113503347735515965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113503347735515965' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113503347735515965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113503347735515965'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/12/sql-reporting-services-alternating.html' title='SQL Reporting Services: Alternating Item Color'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113459469252283647</id><published>2005-12-14T14:07:00.000-07:00</published><updated>2005-12-14T14:22:44.373-07:00</updated><title type='text'>Drive Type</title><content type='html'>I am currently working on a project that imports data from a SD card and I wanted an easy way to find the drive letter that windows creates for the device so that it was defaulted for the user. After a bit of searching I found that I could use WMI to do this and it is quite easy. Here is my implementation:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;    Public Enum DiskDriveType&lt;br /&gt;        Unkown = 0&lt;br /&gt;        NotRootDirectory = 1&lt;br /&gt;        RemovableDisk = 2&lt;br /&gt;        LocalDisk = 3&lt;br /&gt;        NetworkDrive = 4&lt;br /&gt;        CompactDisk = 5&lt;br /&gt;        RamDisk = 6&lt;br /&gt;    End Enum&lt;br /&gt;&lt;br /&gt;    Public Function DriveType(ByVal driveLetter As String) As DiskDriveType&lt;br /&gt;        Dim sms As New System.Management.ManagementObject(String.Format("Win32_logicaldisk='{0}:'", DriveLetter))&lt;br /&gt;        sms.Get()&lt;br /&gt;        Select Case Convert.ToInt32(sms.Properties("DriveType").Value)&lt;br /&gt;            Case 0 : Return DiskDriveType.Unkown&lt;br /&gt;            Case 1 : Return DiskDriveType.NotRootDirectory&lt;br /&gt;            Case 2 : Return DiskDriveType.RemovableDisk&lt;br /&gt;            Case 3 : Return DiskDriveType.LocalDisk&lt;br /&gt;            Case 4 : Return DiskDriveType.NetworkDrive&lt;br /&gt;            Case 5 : Return DiskDriveType.CompactDisk&lt;br /&gt;            Case 6 : Return DiskDriveType.RamDisk&lt;br /&gt;            Case Else : Return DiskDriveType.Unkown&lt;br /&gt;        End Select&lt;br /&gt;    End Function&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;One thing to be warry of is that floppy drives are also considered removable devices so I put a hardcode in to skip the default drive letter for a floppy ("A:\"). I am thinking of improving this in the future to check the capacity of the device to avoid this issue (but then i might get confused between SD cards and external hard drives)&lt;br /&gt;&lt;br /&gt;Usage:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;  For Each driveLetter As String In System.IO.Directory.GetLogicalDrives()&lt;br /&gt;            If driveLetter.Substring(0, 1) &lt;&gt; "A" And DriveType(driveLetter.Substring(0, 1)) = DiskDriveType.RemovableDisk Then&lt;br /&gt;                txtSDDrive.Text = driveLetter&lt;br /&gt;            End If&lt;br /&gt;  Next&lt;/span&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/19004283-113459469252283647?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113459469252283647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113459469252283647' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113459469252283647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113459469252283647'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/12/drive-type.html' title='Drive Type'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113415927237490418</id><published>2005-12-09T13:13:00.000-07:00</published><updated>2005-12-09T13:14:32.383-07:00</updated><title type='text'>Checking if you are connected to the internet</title><content type='html'>I have not tested this but it looks legit:&lt;br /&gt;&lt;br /&gt;[DllImport("wininet.dll")]private extern static bool InternetGetConnectedState    (out int connectionDescription, int reservedValue ) ;&lt;br /&gt;&lt;br /&gt;public bool IsConnected() {   &lt;br /&gt;int connectionDescription = 0;  &lt;br /&gt;return InternetGetConnectedState(out connectionDescription, 0);&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113415927237490418?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113415927237490418/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113415927237490418' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113415927237490418'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113415927237490418'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/12/checking-if-you-are-connected-to.html' title='Checking if you are connected to the internet'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113414525348376236</id><published>2005-12-09T09:16:00.000-07:00</published><updated>2005-12-09T09:58:44.770-07:00</updated><title type='text'>Refactoring and comments</title><content type='html'>If you have not read Martin Fowlers book Refactoring then you should. There is no book that I have read that has helped me more in what I do everyday. The book basically gives techniques on how to make code better and easier to work with after it has been written. One of the most used and common refactorings is "extract method". This is where you take a chunk of code and pull it into its own method. (eg. &lt;a href="http://www.refactoring.com/catalog/extractMethod.html"&gt;http://www.refactoring.com/catalog/extractMethod.html&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;I so love the idea that a method does one task and that is it. If it does two tasks then the method calls two methods (one for each task).&lt;br /&gt;&lt;br /&gt;Now that I have been using this technique for a while I have found that you don't need comments anymore. The reason for this is that when you break everything into small and well named function that anyone can read the code without comments.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if I gave a method like this:&lt;br /&gt;function LoadTransactionType() as boolean&lt;br /&gt;sub SelectFirstRow()&lt;br /&gt;sub AddTransaction()&lt;br /&gt;sub DeleteTransaction()&lt;br /&gt;&lt;br /&gt;It is pretty easy to see what these methods do and the code in those methods only has 5 - 20 lines of code which then might call another simply named method.&lt;br /&gt;&lt;br /&gt;I have now noticed that whenever I open code I look for comments. Comments usually indicate that the code is doing something not obvious so I extract the method and delete the comment.&lt;br /&gt;&lt;br /&gt;I still feel weird that most of my code now has little to no comments in it but it is still increddibly readable and easy to follow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113414525348376236?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113414525348376236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113414525348376236' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113414525348376236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113414525348376236'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/12/refactoring-and-comments.html' title='Refactoring and comments'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113391112594521722</id><published>2005-12-06T16:13:00.000-07:00</published><updated>2005-12-06T16:23:32.973-07:00</updated><title type='text'>SQL Reporting Services: Deploying Reports To Production</title><content type='html'>I can not beleive how hard it is to deploy reports to production! Its easy for development. Just tell visual studio where the server is and bang! its done. I spent most of today trying to figure out how to deploy to production without having to manually upload each report through the web interface and then manually linking them to my shared data source.&lt;br /&gt;&lt;br /&gt;I tried writing a vb script to do it which I got 90% their but could not link to a shared datasource. Microsofts documentation of the scripting commands you can do ARE GARBAGE! when trying to set a property you need to send a name value pair (which is fine) but there is no docs I could find that say what the strings are that I can pass to it. But I digress.&lt;br /&gt;&lt;br /&gt;In the end I found this tool:&lt;br /&gt;http://www.sqldbatips.com/showarticle.asp?ID=62&lt;br /&gt;&lt;br /&gt;This person wrote a tool that connects to my development RS and generates a folder of scripts along with a batch file to run them all. I opened the batch file, changed the server to production and a couple of minutes later I was .....happy? yes. that is the word.&lt;br /&gt;&lt;br /&gt;For those of you that want to deploy reports with a shared datasource via a manual script (using the rs.exe program to execute it) here is a snip of one of the scripts:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Public Sub Main()&lt;br /&gt; Dim name As String = "Allocation Report"&lt;br /&gt; Dim parent As String = "/MyProgram.ReportStaging"&lt;br /&gt; Dim location As String = "c:\tempreports\Allocation Report.rdl"&lt;br /&gt; Dim overwrite As Boolean = True&lt;br /&gt; Dim reportContents As Byte() = Nothing&lt;br /&gt; Dim warnings As Warning() = Nothing&lt;br /&gt; Dim fullpath As String = parent + "/" + name&lt;br /&gt;&lt;br /&gt; 'Common CatalogItem properties&lt;br /&gt; Dim descprop As New [Property]&lt;br /&gt; descprop.Name = "Description"&lt;br /&gt; descprop.Value = ""&lt;br /&gt; Dim hiddenprop As New [Property]&lt;br /&gt; hiddenprop.Name = "Hidden"&lt;br /&gt; hiddenprop.Value = "False"&lt;br /&gt;&lt;br /&gt; Dim props(1) As [Property]&lt;br /&gt; props(0) = descprop&lt;br /&gt; props(1) = hiddenprop&lt;br /&gt;&lt;br /&gt; 'Read RDL definition from disk&lt;br /&gt; Try&lt;br /&gt;  Dim stream As FileStream = File.OpenRead(location)&lt;br /&gt;  reportContents = New [Byte](stream.Length) {}&lt;br /&gt;  stream.Read(reportContents, 0, CInt(stream.Length))&lt;br /&gt;  stream.Close()&lt;br /&gt;&lt;br /&gt;  warnings = RS.CreateReport(name, parent, overwrite, reportContents, props)&lt;br /&gt;&lt;br /&gt;  If Not (warnings Is Nothing) Then&lt;br /&gt;   Dim warning As Warning&lt;br /&gt;   For Each warning In warnings&lt;br /&gt;    Console.WriteLine(Warning.Message)&lt;br /&gt;   Next warning&lt;br /&gt;  Else&lt;br /&gt;   Console.WriteLine("Report: {0} published successfully with no warnings", name)&lt;br /&gt;  End If&lt;br /&gt;&lt;br /&gt;  'Set report DataSource references&lt;br /&gt;  Dim dataSources(0) As DataSource&lt;br /&gt;&lt;br /&gt;  Dim dsr0 As New DataSourceReference&lt;br /&gt;  dsr0.Reference = "/MyProgram.ReportStaging/dsMyProgram"&lt;br /&gt;  Dim ds0 As New DataSource&lt;br /&gt;  ds0.Item = CType(dsr0, DataSourceDefinitionOrReference)&lt;br /&gt;  ds0.Name="dsMyProgram"&lt;br /&gt;  dataSources(0) = ds0&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  RS.SetReportDataSources(fullpath, dataSources)&lt;br /&gt;&lt;br /&gt;  Console.Writeline("Report DataSources set successfully")&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; Catch e As IOException&lt;br /&gt;  Console.WriteLine(e.Message)&lt;br /&gt; Catch e As SoapException&lt;br /&gt;  Console.WriteLine("Error : " + e.Detail.Item("ErrorCode").InnerText + " (" + e.Detail.Item("Message").InnerText + ")")&lt;br /&gt; End Try&lt;br /&gt;End Sub&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/19004283-113391112594521722?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113391112594521722/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113391112594521722' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113391112594521722'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113391112594521722'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/12/sql-reporting-services-deploying.html' title='SQL Reporting Services: Deploying Reports To Production'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113380030979963584</id><published>2005-12-05T09:28:00.000-07:00</published><updated>2005-12-06T13:13:29.443-07:00</updated><title type='text'>LostFocus = Crap?</title><content type='html'>I discovered something interesting with the LostFocus method. Leaving a feild by clicking out of it does not always fire the LostFocus event. The reason for this (from my understanding) is that if the control runs through validation the CancelEventArgs object is set to true. This causes all events after it (in this case LostFocus) to not be fired. &lt;br /&gt;&lt;br /&gt;In order to work around this use the Leave, Validating, or Validated events.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113380030979963584?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113380030979963584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113380030979963584' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113380030979963584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113380030979963584'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/12/lostfocus-crap.html' title='LostFocus = Crap?'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113347920145273766</id><published>2005-12-01T16:02:00.000-07:00</published><updated>2005-12-01T16:20:01.513-07:00</updated><title type='text'>.NET: String Comparisons</title><content type='html'>typically most developers compare strings in a case instensitive way like this:&lt;br /&gt;&lt;br /&gt;if var.toLower = "expected" then &lt;br /&gt;    ...&lt;br /&gt;end if&lt;br /&gt;&lt;br /&gt;this way is a little inneficient and does not take into account cultural differnces (some languages use groups of letters to signify one letter, some letters follow uppercase / lowercase rules differently).&lt;br /&gt;&lt;br /&gt;for comparisons I use this everywhere now:&lt;br /&gt;&lt;br /&gt;If String.Compare(var, "expected", True) = 0 Then&lt;br /&gt;...&lt;br /&gt;end if&lt;br /&gt;&lt;br /&gt;I wish it would return a boolean though. &lt;br /&gt;it returns less than 0 is var is less than expected&lt;br /&gt;0 if they are equal&lt;br /&gt;greater than 0 if expected is greater than var&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113347920145273766?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113347920145273766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113347920145273766' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113347920145273766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113347920145273766'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/12/net-string-comparisons.html' title='.NET: String Comparisons'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113347045762065572</id><published>2005-12-01T13:36:00.000-07:00</published><updated>2005-12-01T13:54:39.030-07:00</updated><title type='text'>Debug and release config files</title><content type='html'>One of my biggest issues was having certain lines in my config file for working in my developement shop and others for production. Whenever a bug was found or the application was released you would have to swap configs around. After a few years of reading I happened accross this method:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;AppDomain.CurrentDomain.SetData()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The first paramaeter is the name of the domain property we want to change, and the second is the value.&lt;br /&gt;&lt;br /&gt;I have this line in my application as the first line of code to be called&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;#If DEBUG Then&lt;br /&gt;     AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "c:\debug.config")&lt;br /&gt;#End If&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;you can also retreive the data using this:&lt;br /&gt;appDomain.CurrentDomain.GetData("APP_CONFIG_FILE")&lt;br /&gt;&lt;br /&gt;for a list of items you can use with get/set data look here:&lt;br /&gt;&lt;a href="ms-help://MS.VSCC.2003/MS.MSDNQTR.2004OCT.1033/cpref/html/frlrfsystemappdomainclassgetdatatopic.htm"&gt;ms-help://MS.VSCC.2003/MS.MSDNQTR.2004OCT.1033/cpref/html/frlrfsystemappdomainclassgetdatatopic.htm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;now that I write this posting it looks like the same can be done in a more managed way by using&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;appDomain.CurrentDomain.SetupInformation.ConfigurationFile = "c:\debug.config"&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113347045762065572?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113347045762065572/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113347045762065572' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113347045762065572'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113347045762065572'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/12/debug-and-release-config-files.html' title='Debug and release config files'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113286777030386323</id><published>2005-11-24T14:25:00.000-07:00</published><updated>2005-11-24T14:29:30.310-07:00</updated><title type='text'>How did I miss this? not that I care.</title><content type='html'>I discovered an "interesting" feature in vs2003 (and assumedly others). For a winform application when I went to "add new item" there is an entry in their called "Data Form Wizard". This little wizard allows you to connect to a database and build a quick screen that is bound to the data that you can add, edit, delete from. It looks terrible, it has no sepration of tiers but if I need to make a quick screen to access a database this tool saves tons of time. I think there is also an output to a datagrid so that you can edit in the grid. I don't have a ton of time to play with it but its still handy. I would not recommend using it for any quality code but damn its fast :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113286777030386323?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113286777030386323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113286777030386323' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113286777030386323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113286777030386323'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/how-did-i-miss-this-not-that-i-care.html' title='How did I miss this? not that I care.'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113284715373613052</id><published>2005-11-24T08:33:00.000-07:00</published><updated>2005-11-24T08:48:49.806-07:00</updated><title type='text'>Exceptions are good</title><content type='html'>I have been playing with FxCop for the past 4 months and I just love it. For those of you who don't know FxCop is a code analysis tool that spots violations of coding standards, i.e. casing of methods, parameters,etc. but it also makes recomendations like when to convert a method to a property, when to make a method static / shared, unused methods / fields, and a whole host of other things. You can get it from &lt;a href="http://www.gotdotnet.com"&gt;www.gotdotnet.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This program recommends that any public method that takes an object be checked to see if the obejct is null and throw an exception if it is.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;public sub DoTask(addy as Address)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;if addy is nothing then throw new ArgumentNullException("addy")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;end sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I though this was a lot of extra work but the second a null object gets passed to a method I catch it right where it happens instead of further down the call stack where the object might actually be called. Also when I get the exception I know exatly where to look to solve the issue instead of getting an "object reference not set to an instance of an object" exception somewhere in my code.&lt;br /&gt;&lt;br /&gt;Another thing that has really helped (and I did not think it would) was writing in methods that I was going to write later (I have a huge select case statement to handle menu item clicks). In a lot of spots I throw NotImplementedExceptions with details of what is not implemented as the argument. Now I quickly see where I have work to do by searching the code (I could use TODO's I know but usually TODO's are for thinks that are partially complete). Also when testing I get that exception and know that I really need to do that chunk of code as it is accessable to the client in the next itteration.&lt;br /&gt;&lt;br /&gt;I have also started making my own generic exception classes. Mainly for the different layers to add a bit of distinction between where an exception happened.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;&lt;br /&gt;   &amp;lt;Serializable()&amp;gt; _&lt;br /&gt;    Public Class GrowerBusinessException&lt;br /&gt;        Inherits Exception&lt;br /&gt;&lt;br /&gt;        Public Sub New(ByVal message As String)&lt;br /&gt;            MyBase.New(message)&lt;br /&gt;        End Sub&lt;br /&gt;&lt;br /&gt;        Public Sub New()&lt;br /&gt;            MyBase.New()&lt;br /&gt;        End Sub&lt;br /&gt;&lt;br /&gt;        Public Sub New(ByVal message As String, ByVal innerException As Exception)&lt;br /&gt;            MyBase.New(message, innerException)&lt;br /&gt;        End Sub&lt;br /&gt;&lt;br /&gt;        Protected Sub New(ByVal serializationInfo As System.Runtime.Serialization.SerializationInfo, ByVal streamingContext As System.Runtime.Serialization.StreamingContext)&lt;br /&gt;            MyBase.new(serializationInfo, streamingContext)&lt;br /&gt;        End Sub&lt;br /&gt;&lt;br /&gt;    End Class&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;pretty simple? I think so and it is nice to be able to quickly look at a logged exception and spot where the exception happened even by its type.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113284715373613052?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113284715373613052/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113284715373613052' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113284715373613052'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113284715373613052'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/exceptions-are-good.html' title='Exceptions are good'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113270356304461392</id><published>2005-11-22T16:48:00.000-07:00</published><updated>2005-11-24T08:33:28.213-07:00</updated><title type='text'>VB.NET: Stupid ands!</title><content type='html'>&lt;span style="font-family:georgia;"&gt;this statement will fail if the column is dbnull&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;if not reader.item("age") is dbnull.value and reader.item("age") &lt;&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;....&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;font-size:100%;color:#000000;"&gt;It fails because vb for some reason evaluates all conditions in the statement and then determines wether it is true or false. To get around this use andalso&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;if not reader.item("age") is dbnull.value andAlso reader.item("age") &lt;&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;....&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:georgia;font-size:100%;color:#000000;"&gt;this will evaluate the first condition and if the first condition is true it will evaluate the second one. This can also be usefull when the second statement is process intensive.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&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/19004283-113270356304461392?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113270356304461392/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113270356304461392' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113270356304461392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113270356304461392'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/vbnet-stupid-ands.html' title='VB.NET: Stupid ands!'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113269146584884759</id><published>2005-11-22T13:29:00.000-07:00</published><updated>2005-11-22T13:31:05.860-07:00</updated><title type='text'>SQL: not so handy function</title><content type='html'>I ran into a strange situation today. I need to make a comma seperated list of values in tsql here is what I came up with&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;declare @cycles varchar(8000)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;set @cycles = ''&lt;br /&gt;SELECT  @cycles = @cycles + CAST(producer_cycle_id AS varchar(100)) + ', '&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;from  cycles&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Note that this function does not work very with nulls (hence why @cycles is initialized to ''. If you have null data make sure you have an isnull() in their to convert it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113269146584884759?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113269146584884759/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113269146584884759' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113269146584884759'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113269146584884759'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/sql-not-so-handy-function.html' title='SQL: not so handy function'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113268510870559619</id><published>2005-11-22T11:35:00.000-07:00</published><updated>2005-11-22T11:45:12.380-07:00</updated><title type='text'>SQL: Handy function</title><content type='html'>I have a lot of stored procedures that I need to retreive, update, delete multiple records based on ID (usually on a screen where a user can select the customers to run a report on). I have seen a lot of developers create dynamic sql (which I hate) or call the same stored proc multiple times (which I hate). I created a little sql function that takes a string of delmited data and turns it into a table:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;CREATE fuNCTION fnStringToCol (@data varchar(8000), @delimiter varchar(100))&lt;br /&gt;RETURNS @output TABLE (data varchar(8000))&lt;br /&gt;AS&lt;br /&gt;BEGIN&lt;br /&gt; declare @position int&lt;br /&gt; declare @start int&lt;br /&gt; declare @end int&lt;br /&gt; declare @part varchar(8000)&lt;br /&gt; &lt;br /&gt; if (charindex(@delimiter, @data) = 0) --if only one value append a , so that it still gets parsed&lt;br /&gt;  set @data = @data + ','&lt;br /&gt;&lt;br /&gt; set @position = charindex(@delimiter, @data)&lt;br /&gt; insert into @output values (ltrim(rtrim(substring(@data, 0, @position))))&lt;br /&gt;&lt;br /&gt; while ((charindex(@delimiter, @data, @position)) &lt;&gt; 0)&lt;br /&gt; begin&lt;br /&gt;  set @start = charindex(@delimiter, @data, @position)&lt;br /&gt;  set @end = charindex(@delimiter, @data, @start+1)&lt;br /&gt;  if (@end = 0)&lt;br /&gt;   set @end = len(@data) - @start&lt;br /&gt; &lt;br /&gt;  set @part =  ltrim(rtrim(substring(@data, @start+1, abs(@end - @start-1))))&lt;br /&gt;  insert&lt;br /&gt;  into @output&lt;br /&gt;  values (@part)&lt;br /&gt;  set @position = charindex(@delimiter, @data, @position) + 1&lt;br /&gt; end&lt;br /&gt; return&lt;br /&gt;END&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-family:Arial;font-size:85%;color:#3366ff;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#3366ff;"&gt;&lt;span style="color:#000000;"&gt;To use this is quite easy:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;font-size:85%;color:#3366ff;"&gt;declare @producers&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;font-size:85%;color:#3366ff;"&gt;set @producers = '1,7,35,26'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;font-size:85%;color:#3366ff;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;color:#3366ff;"&gt;select   * &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;color:#3366ff;"&gt;from     producer &lt;/span&gt;&lt;br /&gt;&lt;span style="color:#3366ff;"&gt;&lt;span style="font-size:85%;"&gt;where  producer_id in (select * from dbo.fnStringToCol(@producers, ','))&lt;/span&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/19004283-113268510870559619?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113268510870559619/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113268510870559619' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113268510870559619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113268510870559619'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/sql-handy-function.html' title='SQL: Handy function'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113233994743384643</id><published>2005-11-18T11:45:00.000-07:00</published><updated>2005-11-18T11:52:27.443-07:00</updated><title type='text'>Tools that make me moist in the pants</title><content type='html'>It has been a long time since I saw a peice of software (Especially a plugin) that makes me go "Wow how did I ever live without this / why didn't I think of that?". I have only played with the IE Dev toolbar for 5 mins now and I had to write about it.&lt;br /&gt;&lt;br /&gt;1. Allows you to hightlight all tables or table cells or divs on a page&lt;br /&gt;2. Show the DOM of a page in a handy little treeview&lt;br /&gt;3. Easily disable Cache, Images, Cookies, script, or the popup blocker&lt;br /&gt;4. Validate a pages HTML, CSS, XHTML, Feed, links, and some other stuff I don't know about&lt;br /&gt;5. Show image dimensions, filesizes, alt tags, and paths&lt;br /&gt;6. Resize the browser window to any size you want (great for testing a site that needs to be 800x600 compatible)&lt;br /&gt;7. Shortcuts to clear cookies, cache, and possibly session (i.e. server side cookies)&lt;br /&gt;8. A ruler that you can draw on a page and get the pixel measurements of items on the page&lt;br /&gt;&lt;br /&gt;thats what I have discovered in ten minutes.&lt;br /&gt;&lt;br /&gt;The IE download is here:&lt;br /&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=e59c3964-672d-4511-bb3e-2d5e1db91038&amp;displaylang=en"&gt;http://www.microsoft.com/downloads/details.aspx?FamilyID=e59c3964-672d-4511-bb3e-2d5e1db91038&amp;amp;displaylang=en&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Also for the Mozilla/Firefox people out there there is apparently a tool like it that can be found here:&lt;br /&gt;&lt;a href="http://chrispederick.com/work/webdeveloper/"&gt;http://chrispederick.com/work/webdeveloper/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113233994743384643?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113233994743384643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113233994743384643' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113233994743384643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113233994743384643'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/tools-that-make-me-moist-in-pants.html' title='Tools that make me moist in the pants'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113232777249878342</id><published>2005-11-18T08:16:00.000-07:00</published><updated>2005-11-18T08:34:10.160-07:00</updated><title type='text'>AJAX: I finally caved!</title><content type='html'>I had played a little with AJAX (Async Java and XML) but I finally caved and started to use it in an app. I must say that it is pretty freakin sweet but I am still concerned (as always with javascript) how it will behave in different browsers and operating sysystems.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;&amp;lt;script&amp;gt;&lt;br /&gt;function CreateRequestObject()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;if (navigator.appName == "Microsoft Internet Explorer") &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;return new ActiveXObject("Microsoft.XMLHTTP")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;else &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;return new XMLHttpRequest();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;var http = CreateRequestObject();&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;function getData()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;http.open('get', 'info.ext') &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;http.onreadystatechange = handleResponse &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;http.send(null);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;function handleResponse()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;if (http.readyState == 4) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;var data = http.responseText; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;var arr = data.split(""); &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;alert(arr[0]); &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;}&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;a onclick="getData()" href="#"&amp;gt;get stuff&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now this is a basic example but one thing that I have done that most other samples have done is not use xml at all in this (my info.ext file contains only this: "testtest2"). I have no real need to use xml. xml would take more bandwidth, more complex code, and a dependancy on the microsoft XML parser activeXobject. Simple text parsing will do fine for me :)&lt;br /&gt;&lt;br /&gt;If your info.ext file is a dynamic page (i.e. asp, php, jsp, etc.) and you want to pass parameters to it do this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;function getData(params)&lt;br /&gt;{&lt;br /&gt;http.open('get', 'info.ext' + params)&lt;br /&gt;http.onreadystatechange = handleResponse&lt;br /&gt;http.send(null);&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and then in the html:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;color:#3366ff;"&gt;&amp;lt;a onclick="getData('?action=getdata&amp;id=37)" href="#"&amp;gt;get stuff&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I assume that you can send post data by changing the method to post in the http.open line and then replace the null in http.send() with the post data you want to send. I have not tried this as it is a bit more than I need.&lt;br /&gt;&lt;br /&gt;I hope that gets you started. It really is quite easy even though js is a pain and makes me a little twitchier!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113232777249878342?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113232777249878342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113232777249878342' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113232777249878342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113232777249878342'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/ajax-i-finally-caved.html' title='AJAX: I finally caved!'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113226494304516846</id><published>2005-11-17T15:01:00.000-07:00</published><updated>2005-11-17T15:02:23.053-07:00</updated><title type='text'>Windows User Controls: Transparent Backgrounds</title><content type='html'>For some reason by default user controls do not support background colors making it a real pain when placing the controls on gradient or image backgrounds. to overcome this put the following line in the initilize component method of your user control:&lt;br /&gt;&lt;br /&gt;Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113226494304516846?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113226494304516846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113226494304516846' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113226494304516846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113226494304516846'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/windows-user-controls-transparent.html' title='Windows User Controls: Transparent Backgrounds'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113216227213229046</id><published>2005-11-16T10:20:00.000-07:00</published><updated>2005-11-16T10:35:53.696-07:00</updated><title type='text'>SQL Reporting Services: URL Generation Code</title><content type='html'>Here is a little method I made to build the query string to pass to reporting services.&lt;br /&gt;-showToolbar shows or hides the toolbar with paging, printing, exporting, etc.&lt;br /&gt;-showParameters shows or hides the entry fields that allow a user to change what values the report is generated from&lt;br /&gt;-properties is a name value collection of parameters that you can supply to the report to generate it instead of the user having to type them into the boxes if ShowParameters is on.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;Private Function BuildPropertyString(showToolbar as boolean, showParameters as boolean, properties as NameValueCollection) As String&lt;br /&gt;If _properties Is Nothing Then Return ""&lt;br /&gt;Dim sb As New System.Text.StringBuilder&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;if ShowToolbar then sb.Append("&amp;rc:Toolbar=true")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;font-size:85%;"&gt;if ShowParameters then sb.Append("&amp;amp;rc:Parameters=false&amp;")&lt;br /&gt;For Each key As String In properties.Keys&lt;br /&gt;sb.Append(key)&lt;br /&gt;sb.Append("=")&lt;br /&gt;sb.Append(System.Web.HttpUtility.UrlEncode(properties(key)))&lt;br /&gt;sb.Append("&amp;amp;")&lt;br /&gt;Next&lt;br /&gt;sb.Remove(sb.Length - 1, 1) 'remove the trailing &amp;amp;&lt;br /&gt;Return sb.ToString&lt;br /&gt;End Function&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt;NOTE: this function will exit if no properties are passed to it. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;font-size:85%;"&gt;Also it would have been beter of me to rename properties to parameters now that I look at it :)&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113216227213229046?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113216227213229046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113216227213229046' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113216227213229046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113216227213229046'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/sql-reporting-services-url-generation.html' title='SQL Reporting Services: URL Generation Code'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113215963809751968</id><published>2005-11-16T09:44:00.000-07:00</published><updated>2005-11-16T09:47:18.106-07:00</updated><title type='text'>SQL Reporting Services: Print Layout</title><content type='html'>Working on more reports today and discovered that reports print in standard format and I have several I need to print in landscape mode. I finally figured out how&lt;br /&gt;&lt;br /&gt;goto report -&gt; report properties -&gt; layout&lt;br /&gt;set the width to be 29.7cm&lt;br /&gt;set the height to be 21cm&lt;br /&gt;&lt;br /&gt;I wish there was an option that just said landscape though!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113215963809751968?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113215963809751968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113215963809751968' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113215963809751968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113215963809751968'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/sql-reporting-services-print-layout.html' title='SQL Reporting Services: Print Layout'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113208908832596797</id><published>2005-11-15T14:04:00.000-07:00</published><updated>2005-11-15T14:11:28.333-07:00</updated><title type='text'>SQL Reporting Services: Formatting Data</title><content type='html'>One of the cool things I discovered today was that you can use .NET formatting codes when formatting data for output with reporting services&lt;br /&gt;&lt;br /&gt;1. Right Click on the field&lt;br /&gt;2. goto properties&lt;br /&gt;3. Check the Custom Radio box and type one in&lt;br /&gt;&lt;br /&gt;you can type in 'c' for currency formatting that is locale specific, 'd' for decimal output, or 'p' for percentage.&lt;br /&gt;&lt;br /&gt;I needed a custom one that had a number formatted by commas with no decimal places so I simply typed in ###,###,### and viola!&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;More info on format strings&lt;br /&gt;&lt;/strong&gt;Standard numeric formattings: &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconstandardnumericformatstrings.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconstandardnumericformatstrings.asp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Custom numeric formattings: &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcustomnumericformatstrings.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconcustomnumericformatstrings.asp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Date time formatting: &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemGlobalizationDateTimeFormatInfoClassTopic.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemGlobalizationDateTimeFormatInfoClassTopic.asp&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;strong&gt;&lt;/strong&gt;&lt;strong&gt;&lt;br /&gt;&lt;/strong&gt;&lt;strong&gt;&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113208908832596797?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113208908832596797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113208908832596797' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113208908832596797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113208908832596797'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/sql-reporting-services-formatting-data.html' title='SQL Reporting Services: Formatting Data'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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-19004283.post-113217627380534369</id><published>2005-11-14T14:14:00.000-07:00</published><updated>2005-11-16T15:05:59.363-07:00</updated><title type='text'>SQL Reporting Services: Impression after two weeks</title><content type='html'>Beefs:&lt;br /&gt;&lt;br /&gt;1. Report wizard comes back with weird errors when a query is not right. When you run it in query analyzer the actuall issue gets reported and is easy to correct.&lt;br /&gt;2. Can not use a stored proc that has multiple result sets.&lt;br /&gt;3. The report wizard will not work in some scenarios when using a temp table or a table variable.&lt;br /&gt;4. MSDN documentation = the suck&lt;br /&gt;5. The designer in visual studio does not remember the parameters entered when switching between layout and preview mode&lt;br /&gt;6. I can not find a place to change my rules to metric.&lt;br /&gt;7. Does not seem to be any way to pass a dataset to it or an XML file. I really liked this feature in crystal especially when the reporting layer does not have permssions / access to the physical database&lt;br /&gt;8. Data designer does not like it when objects have different owners. i.e. (I am calling dbo.sp_report which internally joins to a view not owned by dbo... might work if I prefix the view with the owner though)&lt;br /&gt;9. Expressions are VB based which is case insensitive but field names ARE case sensitive!&lt;br /&gt;hence the expression below do not evaluate the same.&lt;br /&gt;iif(Fields!Transaction_Type_code.Value = "BRM", Fields!amount.Value, "")&lt;br /&gt;iif(Fields!Transaction_type_code.Value = "BRM", Fields!amount.Value, "")&lt;br /&gt;&lt;br /&gt;Pros:&lt;br /&gt;1. Easy to use&lt;br /&gt;2. .NET formatting support&lt;br /&gt;3. Easy to export reports&lt;br /&gt;4. Easy to design simple reports&lt;br /&gt;5. Integrated designer is awsome as I don't have to publish to preview or reset any databindings&lt;br /&gt;6. Many methods to use the system (url, soap, etc.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;EDIT: Ok you can connect datasets to the report but seems a little involved&lt;br /&gt;&lt;a href="http://msdn.microsoft.com/SQL/2000/learn/bi/reporting/default.aspx?pull=/library/en-us/dnsql2k/html/rsdsetex3.asp"&gt;http://msdn.microsoft.com/SQL/2000/learn/bi/reporting/default.aspx?pull=/library/en-us/dnsql2k/html/rsdsetex3.asp&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/19004283-113217627380534369?l=kudos2u2.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kudos2u2.blogspot.com/feeds/113217627380534369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=19004283&amp;postID=113217627380534369' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113217627380534369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/19004283/posts/default/113217627380534369'/><link rel='alternate' type='text/html' href='http://kudos2u2.blogspot.com/2005/11/sql-reporting-services-impression.html' title='SQL Reporting Services: Impression after two weeks'/><author><name>Kudos</name><uri>http://www.blogger.com/profile/01817541369041474300</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>
