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

<channel>
	<title>Pearl Tech &#187; Geer</title>
	<atom:link href="http://blog.pearltechnology.com/author/geers/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.pearltechnology.com</link>
	<description></description>
	<lastBuildDate>Tue, 25 May 2010 14:37:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Enterprise Library Logger.Write Not Working?</title>
		<link>http://blog.pearltechnology.com/enterprise-library-logger-write-not-working/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://blog.pearltechnology.com/enterprise-library-logger-write-not-working/#comments</comments>
		<pubDate>Mon, 17 May 2010 21:29:50 +0000</pubDate>
		<dc:creator>Geer</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Enterprise Library]]></category>
		<category><![CDATA[Logger]]></category>

		<guid isPermaLink="false">http://blog.pearltechnology.com/?p=697</guid>
		<description><![CDATA[Using Logging Application Block provided by Enterprise Library is a common way of logging exceptions in .NET applications.  It&#8217;s easy to setup and to use.  One problem I had a while ago was that it worked while on my development PC, but stopped working once it&#8217;s deployed.
What I was doing was to use it to [...]]]></description>
			<content:encoded><![CDATA[<p>Using Logging Application Block provided by Enterprise Library is a common way of logging exceptions in .NET applications.  It&#8217;s easy to setup and to use.  One problem I had a while ago was that it worked while on my development PC, but stopped working once it&#8217;s deployed.</p>
<p>What I was doing was to use it to write event entries in windows event log as part of the exception handling in an ASP.NET web application.  Nothing fancy.  It worked fine on my PC, but it didn&#8217;t write anything to the event log when Logger.Write is executed. No exception was thrown from that line of code either.  The program just went through as if that line of code was skipped.</p>
<p>It turned out to be a permission issue. When I debug the application in Visual Studio, it was running under my windows account credential which had permission to create Event Source in the system.  However, when the application was deployed to the server, it was running under the default account which was &#8220;NT Authority\Network Service&#8221; in my case.  By default, that account doesn&#8217;t have permission to create new Event Source in the system.  It does have permission to write event entries though.  So, when Logger.Write was executed, it couldn&#8217;t proceed because the Event Source wasn&#8217;t there, and the program didn&#8217;t have permission to create one.  Actually, it makes sense to not throw any exception on this line, because people like me usually use this to log exceptions, and if the logging process itself throws exceptions, there is probably nowhere else we can handle and/or log them.</p>
<p>Now, how this can be resolve?  The solution is quite simple.  As long as the Event Source is created ahead of time, it will be no problem.  What I did was to create required Event Source(s) on server through CMD.exe.  Here is a sample command:</p>
<p><span style="color: #0000ff"><code>eventcreate /ID 1 /L Application /T information /SO "My Event Source" /D "My Event Source is created."</code></span></p>
<p>This command will create an event entry in the Application log.  If the Event Source doesn&#8217;t exist, it will be created during the process.  This is only required when the application is deployed to the server first time.  So, I usually do it manually on server.  However, if that&#8217;s not the case, you can build it into the installation package, and when the application is installed, the Event Source is created as well.  Of course, you can use .NET to create Event Source in your installer too.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pearltechnology.com/enterprise-library-logger-write-not-working/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exception Handling in ASP.NET Web Application</title>
		<link>http://blog.pearltechnology.com/exception-handling-in-asp-net-web-application/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://blog.pearltechnology.com/exception-handling-in-asp-net-web-application/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 22:14:09 +0000</pubDate>
		<dc:creator>Geer</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Exception Handling]]></category>

		<guid isPermaLink="false">http://blog.pearltechnology.com/?p=687</guid>
		<description><![CDATA[In web application development, we should always think about returning some kind of message to users when an exception is raised in the program.  Sometimes, it can be very specific, while in other cases it can be generic.  A common thought is to capture and possibly handle exceptions where they are raised, re-throw exceptions or [...]]]></description>
			<content:encoded><![CDATA[<p>In web application development, we should always think about returning some kind of message to users when an exception is raised in the program.  Sometimes, it can be very specific, while in other cases it can be generic.  A common thought is to capture and possibly handle exceptions where they are raised, re-throw exceptions or raise custom exceptions as needed so they can propagate up to higher level tiers in the application, handle/log exceptions at a central place in the highest tier of the application, and finally display an error message to the end-users or redirect them to a customized error page.</p>
<p>This pattern works, but sometimes it is tricky to generate a meaningful message.  The problem is that the exception can be thrown anywhere in your application, and the exception message may not always be appropriate or meaningful to end-users.  If you blindly display all exception messages you finally get, users may see something like &#8220;Object reference not set to an instance of an object&#8221; which doesn&#8217;t mean much to them.  So, in the final step of exception handling (where the program displays error messages or redirect users to an error page), you will see all kinds of exceptions which include .NET originated exceptions, exceptions raised by the program on purpose, and custom exceptions.  Some of them are appropriate to show to users, while others aren&#8217;t.  So, the question is how you can distinguish among them.</p>
<p>A lot of people suggest that if the original .NET exception message isn&#8217;t meaningful to users, and you can&#8217;t provide more specific message either, then a generic message such as &#8220;An error has occurred&#8230;  Please contact the technical support team for help&#8221; can be used.  I agree too.  You may do this where you know an exception can be thrown, and re-throw the exception with customized message (whether specific or generic) and with the original exception embedded as the inner exception of the new exception.  However, you don&#8217;t want to just put try/catch blocks in every piece of your code, and catch and re-throw every exception the program may possibly encounter.  It&#8217;s labor intensive and inefficient.  Also, there will always be something you can&#8217;t think of or look over, so there are still chances you can get unexpected exceptions in the end.</p>
<p>So, my solution is to let the program only catch and re-throw .NET originated exceptions when they are predictable and additional meaningful information can be provided, and let all other exceptions bubble up to the top tier.  Then in the final step of exception handling, identify the exceptions that are re-thrown, and retrieve the error message directly from these exceptions; use a generic error message for all other exceptions.  The question is how to identify these exceptions that are re-thrown.  For this purpose, I usually create a custom exception class which is inherited from System.Exception.  Use this class whenever I need to throw new exceptions or re-throw .NET originated exceptions.  So, in the final step, I check the type of the exception, and decide whether to use it as the error message or use a generic one instead.</p>
<p>Here is the custom exception class:</p>
<div style="border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt">
<div style="background: #ddd;overflow: auto">
<ol style="background: #ffffff;margin: 0 0 0 2.5em;padding: 0 0 0 5px">
<li><span style="color:#0000ff">public</span> <span style="color:#0000ff">class</span> <span style="color:#2b91af">ExceptionBase</span> : <span style="color:#2b91af">Exception</span></li>
<li>{</li>
<li><span style="color:#0000ff">public</span> ExceptionBase(<span style="color:#0000ff">string</span> msg, <span style="color:#2b91af">Exception</span> innerEx)</li>
<li>: <span style="color:#0000ff">base</span>(msg, innerEx)</li>
<li>{</li>
<li>}</li>
<li><span style="color:#0000ff">public</span> ExceptionBase(<span style="color:#0000ff">string</span> msg)</li>
<li>: <span style="color:#0000ff">base</span>(msg)</li>
<li>{</li>
<li>}</li>
<li>}</li>
</ol>
</div>
</div>
<p>The ExceptionBase class has two constructors which give you the options to create an instance of exception with customized error message and with/without inner exception.</p>
<p>Here is how to use it in code:</p>
<div style="border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt">
<div style="background: #ddd;overflow: auto">
<ol style="background: #ffffff;margin: 0 0 0 2em;padding: 0 0 0 5px">
<li><span style="color:#0000ff">throw</span> <span style="color:#0000ff">new</span> <span style="color:#2b91af">ExceptionBase</span>(<span style="color:#a31515">&#8220;Error has occurred in accessing database.&#8221;</span>);</li>
</ol>
</div>
</div>
<p>Or</p>
<div style="border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt">
<div style="background: #ddd;overflow: auto">
<ol style="background: #ffffff;margin: 0 0 0 2em;padding: 0 0 0 5px">
<li><span style="color:#0000ff">try</span></li>
<li>{</li>
<li><span style="color:#008000">// Data access operations</span></li>
<li>}</li>
<li><span style="color:#0000ff">catch</span> (<span style="color:#2b91af">Exception</span> ex)</li>
<li>{</li>
<li><span style="color:#0000ff">throw</span> <span style="color:#0000ff">new</span> <span style="color:#2b91af">ExceptionBase</span>(<span style="color:#a31515">&#8220;Error has occurred in accessing database.&#8221;</span>, ex);</li>
<li>}</li>
</ol>
</div>
</div>
<p>The central location I handle all exceptions is in global.asax, and here is what it looks like:</p>
<div style="border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt">
<div style="background: #ddd;overflow: auto">
<ol style="background: #ffffff;margin: 0 0 0 2.5em;padding: 0 0 0 5px">
<li><span style="color:#0000ff">protected</span> <span style="color:#0000ff">void</span> Application_Error(<span style="color:#0000ff">object</span> sender, <span style="color:#2b91af">EventArgs</span> e)</li>
<li>{</li>
<li><span style="color:#2b91af">Exception</span> ex = Server.GetLastError();</li>
<li><span style="color:#0000ff">string</span> msg = <span style="color:#a31515">&#8220;Unexpected error has occurred.&#8221;</span>;</li>
<li><span style="color:#0000ff">if</span> (ex != <span style="color:#0000ff">null</span>)</li>
<li>{</li>
<li><span style="color:#2b91af">LoggingUtility</span>.LogException(ex);</li>
<li><span style="color:#008000">// Remove the HttpUnhandledException wrapper if there is one</span></li>
<li><span style="color:#0000ff">if</span> (ex.GetType() == <span style="color:#0000ff">typeof</span>(<span style="color:#2b91af">HttpUnhandledException</span>) &amp;&amp; ex.InnerException != <span style="color:#0000ff">null</span>)</li>
<li>{</li>
<li>ex = ex.InnerException;</li>
<li>}</li>
<li><span style="color:#008000">// If this is a custom exception, change the message.</span></li>
<li><span style="color:#0000ff">if</span> (ex <span style="color:#0000ff">is</span> <span style="color:#2b91af">ExceptionBase</span>)</li>
<li>msg = ex.Message;</li>
<li>Server.ClearError();</li>
<li>}</li>
<li><span style="color:#008000">// Try to redirect user.</span></li>
<li>Response.Redirect(<span style="color:#0000ff">string</span>.Format(<span style="color:#a31515">&#8220;~/Error.htm?aspxerrorpath={0}&amp;error={1}&#8221;</span>, <span style="color:#2b91af">HttpUtility</span>.UrlEncodeUnicode(Request.Url.PathAndQuery), msg), <span style="color:#0000ff">true</span>);</li>
<li>}</li>
</ol>
</div>
</div>
<p>One note for this is that ASP.NET may put a wrapper exception (HttpUnhandledException) around the original exception.  In the code above, it is simply removed because it doesn&#8217;t contain any useful information.</p>
<p>You can also create more custom exception classes based on the ExceptionBase class to improve consistency in your application, and the code above will still work.  One example is:</p>
<div style="border: #000080 1px solid;color: #000;font-family: 'Courier New', Courier, Monospace;font-size: 10pt">
<div style="background: #ddd;overflow: auto">
<ol style="background: #ffffff;margin: 0 0 0 2em;padding: 0 0 0 5px">
<li><span style="color:#0000ff">public</span> <span style="color:#0000ff">class</span> <span style="color:#2b91af">BadUrlException</span> : <span style="color:#2b91af">ExceptionBase</span></li>
<li>{</li>
<li><span style="color:#0000ff">public</span> BadUrlException(<span style="color:#2b91af">Exception</span> innerEx)</li>
<li>: <span style="color:#0000ff">base</span>(<span style="color:#a31515">&#8220;Bad URL has been detected. Request could not be processed.&#8221;</span>, innerEx)</li>
<li>{</li>
<li>}</li>
<li>}</li>
</ol>
</div>
</div>
<p>This way the error messages for one type of exception are consistent across the application.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pearltechnology.com/exception-handling-in-asp-net-web-application/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Use Microsoft Device Emulator in VS2008</title>
		<link>http://blog.pearltechnology.com/how-to-use-microsoft-device-emulator-in-vs2008/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://blog.pearltechnology.com/how-to-use-microsoft-device-emulator-in-vs2008/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 13:37:18 +0000</pubDate>
		<dc:creator>Geer</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Device Emulator]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[visual studio 2008]]></category>

		<guid isPermaLink="false">http://blog.pearltechnology.com/?p=658</guid>
		<description><![CDATA[Microsoft Device Emulator is a great tool for testing your mobile web applications without utilizing any real mobile device.  Because it can use the same network that your computer is on, you can use it to test your mobile web applications hosted on development computers or test servers before the applications are published to the internet.  [...]]]></description>
			<content:encoded><![CDATA[<p>Microsoft Device Emulator is a great tool for testing your mobile web applications without utilizing any real mobile device.  Because it can use the same network that your computer is on, you can use it to test your mobile web applications hosted on development computers or test servers before the applications are published to the internet.  It is part of the Visual Studio 2008, so you can set it up with very minimal work, if you already have VS2008 installed.  It can also be installed separately.  In the rest of this post, I will demonstrate how to set it up, to use your local network and access your mobile web applications.</p>
<p>Here are a few things you will need to have on your computer to continue.</p>
<ol>
<li>Windows Virtual PC 2007.  This is required, if you would like to connect the Device Emulator to your local network.  The software can be downloaded from <a title="Download Virutal PC 2007" href="http://www.microsoft.com/windows/virtual-pc/download.aspx" target="_blank">Microsoft website</a>.</li>
<li>Microsoft Visual Studio 2008.</li>
<li>Microsoft Device Emulator (which comes with VS2008).</li>
</ol>
<p>With all the above requirements available on your computer, you can follow the steps below to configure your Device Emulator.</p>
<ol>
<li>Start VS 2008 IDE.</li>
<li>On the menu, go to Tools &gt;&gt; Device Emulator Manager
<div id="attachment_659" class="wp-caption alignnone" style="width: 310px"><img class="size-medium wp-image-659" src="http://blog.pearltechnology.com/wp-content/uploads/2010/03/IDE1-300x233.jpg" alt="Start Device Emulator Manager" width="300" height="233" /><p class="wp-caption-text">Start Device Emulator Manager</p></div></li>
<li>Right-click on a device you would like to use, and choose Connect option.
<p><div id="attachment_660" class="wp-caption alignnone" style="width: 310px"><img class="size-medium wp-image-660" src="http://blog.pearltechnology.com/wp-content/uploads/2010/03/Connect-to-a-mobile-device-300x222.jpg" alt="Connect to A Mobile Device" width="300" height="222" /><p class="wp-caption-text">Connect to A Mobile Device</p></div></li>
<li>After the device is connected, right-click on the connected device again, and choose Cradle.
<p><div id="attachment_661" class="wp-caption alignnone" style="width: 310px"><img class="size-medium wp-image-661" src="http://blog.pearltechnology.com/wp-content/uploads/2010/03/Cradle-Device-300x214.jpg" alt="Cradle the Connected Device" width="300" height="214" /><p class="wp-caption-text">Cradle the Connected Device</p></div></li>
<li>Go to the device window.  On the menu, choose File &gt;&gt; Configure
<p><div id="attachment_662" class="wp-caption alignnone" style="width: 310px"><img class="size-medium wp-image-662" src="http://blog.pearltechnology.com/wp-content/uploads/2010/03/Configure-Device-300x209.jpg" alt="Configure Device" width="300" height="209" /><p class="wp-caption-text">Configure Device</p></div></li>
<li>Go to the Network tab, and select the options as shown in the screen shot below.  And then click OK to close the window.
<p><div id="attachment_663" class="wp-caption alignnone" style="width: 310px"><img class="size-medium wp-image-663" src="http://blog.pearltechnology.com/wp-content/uploads/2010/03/Choose-Network-Card-300x223.jpg" alt="Choose Network Card" width="300" height="223" /><p class="wp-caption-text">Choose Network Card</p></div></li>
<li>In the device window, on the menu, choose File &gt;&gt; Reset &gt;&gt; Soft.  And wait until the device is restarted.</li>
<li>Now you need to configure the internet connection in the mobile device.  (The process could be different depending on what device you have picked.)  Normally, you would find the Settings option in the main menu, and then go to the Connections section to choose/define an internet connection.  Here below I use the device I chose as an example.</li>
<li>Choose Settings &gt;&gt; Connections &gt;&gt; Advanced &gt;&gt; Select Networks, and then choose My ISP for both Internet and Private Network connections.
<p><div id="attachment_668" class="wp-caption alignnone" style="width: 190px"><img class="size-medium wp-image-668" src="http://blog.pearltechnology.com/wp-content/uploads/2010/03/Settings-180x300.jpg" alt="Choose Settings" width="180" height="300" /><p class="wp-caption-text">Choose Settings</p></div>
<div id="attachment_667" class="wp-caption alignnone" style="width: 189px"><img class="size-medium wp-image-667" src="http://blog.pearltechnology.com/wp-content/uploads/2010/03/Connections-179x300.jpg" alt="Choose Connections" width="179" height="300" /><p class="wp-caption-text">Choose Connections</p></div>
<div id="attachment_665" class="wp-caption alignnone" style="width: 190px"><img class="size-medium wp-image-665" src="http://blog.pearltechnology.com/wp-content/uploads/2010/03/Advanced-Settings-180x300.jpg" alt="Choose Advanced Settings" width="180" height="300" /><p class="wp-caption-text">Choose Advanced Settings</p></div>
<p><div id="attachment_666" class="wp-caption alignnone" style="width: 190px"><img class="size-medium wp-image-666" src="http://blog.pearltechnology.com/wp-content/uploads/2010/03/Choose-My-ISP-180x300.jpg" alt="Choose My ISP" width="180" height="300" /><p class="wp-caption-text">Choose My ISP</p></div></li>
<li>After confirming all these changes, you can now visit your mobile web application or internet using this Device Emulator.  Task accomplished!
<p><div id="attachment_669" class="wp-caption alignnone" style="width: 190px"><img class="size-medium wp-image-669" src="http://blog.pearltechnology.com/wp-content/uploads/2010/03/Mobile-Website-180x300.jpg" alt="Your Mobile Website" width="180" height="300" /><p class="wp-caption-text">Your Mobile Website</p></div></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.pearltechnology.com/how-to-use-microsoft-device-emulator-in-vs2008/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting Siebel EIM Process Batch Number in Command Line</title>
		<link>http://blog.pearltechnology.com/setting-siebel-eim-process-batch-number-in-command-line/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://blog.pearltechnology.com/setting-siebel-eim-process-batch-number-in-command-line/#comments</comments>
		<pubDate>Thu, 25 Mar 2010 15:02:19 +0000</pubDate>
		<dc:creator>Geer</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[BATCH]]></category>
		<category><![CDATA[Command]]></category>
		<category><![CDATA[EIM]]></category>
		<category><![CDATA[Siebel]]></category>

		<guid isPermaLink="false">http://blog.pearltechnology.com/?p=628</guid>
		<description><![CDATA[My customer&#8217;s current process of importing data into Siebel database is to use Siebel EIM interface.  The data which needs to be imported will be formatted and inserted into EIM tables (or the staging tables), and then an EIM process will be ticked off in the command line to import the data into Siebel base [...]]]></description>
			<content:encoded><![CDATA[<p>My customer&#8217;s current process of importing data into Siebel database is to use Siebel EIM interface.  The data which needs to be imported will be formatted and inserted into EIM tables (or the staging tables), and then an EIM process will be ticked off in the command line to import the data into Siebel base tables.  The command is fairly simple, and should be similar to the following:</p>
<p><span style="color: #0000ff;font-family: Courier New">[Path to The Siebel Application Bin folder]\srvrmgr.exe /g [Siebel Application Server Name] /e [Target Siebel Environment] /s [Siebel Application Server Name] /u [User Name] /p [User Password]</span></p>
<p><span style="color: #0000ff;font-family: Courier New"><br />
run task for component EIM with config=&#8221;[Config File].ifb&#8221;,Process=&#8221;[Process Name]&#8220;</span></p>
<p>The first command starts the srvrmgr program, and the second one ticks off the EIM process.  The configuration file ([config File].ifb) specifies all the parameters needed by the EIM interface in order to complete the process.  One of the important parameters we need to set in the .ifb file is the BATCH, which is the identifier for the group of data being handled during the current process.  Normally, we set it to a fixed number or a range of numbers (for example, 500-600).  So, when the EIM process runs, only the data with a batch number equal to the BATCH or falling in the range specified in the .ifb file will be processed.  If in the EIM tables there are some records which are not ready to be processed at this moment, they can be skipped by identifying themselves with a different batch number.  This is helpful when you are managing multiple data importing tasks which share the same set of EIM tables, and run at different time.</p>
<p>However, we soon realized that it would be getting harder and harder to manage these .ifb files and to make sure these EIM processes don&#8217;t interfere with each other.  For example, one of our custom applications needs to import data into Siebel using EIM interface upon users&#8217; requests.  The data importing process is exactly the same for all these requests, except for the data needed to be imported.  Multiple users need to be allowed to submit their requests at the same time, and their requests should be handled separately.  If we were going to do it in the old fashion, we would need to have a .ifb file for each of their requests, and use different batch numbers in these .ifb files.  It is not realistic, or it is something we want to do either.</p>
<p>The solution is actually very simple.  We took the BATCH setting out of the .ifb file, and instead we set it in the command line.  This was not documented in the Siebel EIM Admin Guide, but after our testing it was proved to be a working solution.  The command will look like the following now:</p>
<p><span style="color: #0000ff;font-family: Courier New">[Siebel Application Bin folder]\srvrmgr.exe /g [Siebel Application Server Name] /e [Target Siebel Environment] /s [Siebel Application Server Name] /u [User Name] /p [User Password]</span></p>
<p><span style="color: #0000ff;font-family: Courier New"><br />
run task for component EIM with config=&#8221;[Config File].ifb&#8221;,Process=&#8221;[Process Name]&#8220;<span style="color: #ff0000">,BATCH=[Batch Number]</span></span></p>
<p>This way the application can choose a BATCH number unique to the user&#8217;s request, construct the command, and then execute it to tick off the EIM process, and all these requests can share the same .ifb file.</p>
<p>To manage the batch numbers among different applications, we reserved a range of batch numbers for each application.  For example, from 500 to 549 will be used only by application A, and from 550 to 599 will be used only by application B.  Within each application, a batch number is assigned to each request based on the request identifier and the range of batch numbers reserved for the application.  In our case, the request ID is an auto-incrementing integer, and the equation for calculating the batch number is:</p>
<p><span style="color: #0000ff;font-family: Courier New">[Batch Number] = [Request ID] % [Total Number of Allocated Batch Numbers] + [The Lowest Batch Number]<br />
(Where % stands for the modulus operator)</span></p>
<p>For example, if the allocated batch numbers are from 500 to 549, and the current request ID is 1034, the batch number for this request will then be:</p>
<p><span style="color: #0000ff;font-family: Courier New">534 = 1034 % (549 &#8211; 500 + 1) + 500</span></p>
<p>This way the adjacent requests would have different batch numbers, and the batch numbers are used in a cycle.  In our case, we will never have more than 50 users submitting their requests at the same time, but if this was for a larger user base, we could allocated a bigger range of batch numbers.</p>
<p>So, we finally were able to manage all users&#8217; requests using limited batch numbers and a single .ifb file without the requests being interfered by each other.  Task accomplished!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pearltechnology.com/setting-siebel-eim-process-batch-number-in-command-line/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FileUpload Control not working in UpdatePanel</title>
		<link>http://blog.pearltechnology.com/fileupload-control-not-working-in-updatepanel/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://blog.pearltechnology.com/fileupload-control-not-working-in-updatepanel/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 16:08:11 +0000</pubDate>
		<dc:creator>Geer</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[FileUpload]]></category>
		<category><![CDATA[UpdatePanel]]></category>

		<guid isPermaLink="false">http://blog.pearltechnology.com/?p=606</guid>
		<description><![CDATA[You may have experienced the problem with FileUpload control in an UpdatePanel – when you hit the submit button, Request.Files.Count always returns 0, even though you had registered the submit button as a PostBackControl and a PostBackTrigger of the UpdatePanel containing the FileUpload control.
In my case, the FileUpload only works when it is visible when [...]]]></description>
			<content:encoded><![CDATA[<p>You may have experienced the problem with FileUpload control in an UpdatePanel – when you hit the submit button, Request.Files.Count always returns 0, even though you had registered the submit button as a PostBackControl and a PostBackTrigger of the UpdatePanel containing the FileUpload control.</p>
<p>In my case, the FileUpload only works when it is visible when the page is first time loaded (not a postback).  It will not work (Request.Files.Count returns 0) when it is hidden originally and then made visible during later AsyncPostBacks.  Maybe ASP.NET is confused, because I am also changing the submit button’s postback type between full postback and aysnc postback.  The submit button is used by other things, and I only want it to fire a full post back when files need to be uploaded, and in all other cases, I want it to fire async postback and only do partial update on my page.</p>
<p>I spent many hours trying many different solutions I saw on the internet, but none of them worked for me.  However, I found an important hint which led me to the final working solution.  That is the Enctype attribute of the Form.  I learned that the Form.Enctype has to be “multipart/form-data” when files need to be uploaded.  I think this is set automatically for you in normal cases, but it isn’t set up correctly in my case.  So, I manually set it to “multipart/form-data” in OnInit of my user control, and it solves the problem.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pearltechnology.com/fileupload-control-not-working-in-updatepanel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>varchar(MAX) parameter slows down Stored Procedure execution?</title>
		<link>http://blog.pearltechnology.com/varcharmax-parameter-slows-down-stored-procedure-execution/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://blog.pearltechnology.com/varcharmax-parameter-slows-down-stored-procedure-execution/#comments</comments>
		<pubDate>Fri, 09 Oct 2009 19:07:40 +0000</pubDate>
		<dc:creator>Geer</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[slow]]></category>
		<category><![CDATA[Stored Procedure]]></category>
		<category><![CDATA[varchar(MAX)]]></category>

		<guid isPermaLink="false">http://blog.pearltechnology.com/?p=406</guid>
		<description><![CDATA[I was testing one of our web applications one day and happened to see a simple Stored Procedure took over a minute to complete.  The Stored Procedure only takes one parameter.  If I get rid of the parameter and directly run the SQL statement inside the Stored Procedure, it took less than a second to [...]]]></description>
			<content:encoded><![CDATA[<p>I was testing one of our web applications one day and happened to see a simple Stored Procedure took over a minute to complete.  The Stored Procedure only takes one parameter.  If I get rid of the parameter and directly run the SQL statement inside the Stored Procedure, it took less than a second to complete.  So, I bet the problem is about the parameter I am passing in the Stored Procedure.  I checked their Execution Plan.  The Execution Plan of the Stored Procedure is much more complex then the simple Query and it has a much higher estimated cost.</p>
<p>I did some research online, and people are saying that the Parameter Sniffing could be the cause.  I tried to avoid it according to this <a href="http://www.eggheadcafe.com/PrintSearchContent.asp?LINKID=1181" target="_blank">post</a>, but it didn&#8217;t make much difference as far as how long it takes for the Stored Procedure to complete.</p>
<p>After trying many different things, I finally found out the problem.  The Stored Procedure was dynamically created from user-defined query using SQL Server Management Object within our .NET web application.  We also allow users to define parameters (such as @Param1) in their Queries.  Since we don&#8217;t know the maximum length of the string parameter, we used varchar(MAX) for all string type parameters.  That&#8217;s the cause of this problem.  Once I changed the varchar(MAX) to varchar(200), the Stored Procedure started running much faster and the Execution Plan looks very similar to the simple Query now.  Problem solved.</p>
<p>Just for curiosity, I compared some other scenarios.  I found out that varchar(MAX) doesn&#8217;t always make a huge difference in performance.  The Stored Procedure I had problem with had a target table in a remote database (Linked Server) and the version of the remote SQL Server is 2000 where varchar(MAX) is not supported.  I am surprised that I didn&#8217;t get any exception when I run the query.  I am not sure what SQL Server does in the back end to make this unsupported data type to work, but apparently it slows down the query execution.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pearltechnology.com/varcharmax-parameter-slows-down-stored-procedure-execution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Use of TransactionScope in .NET</title>
		<link>http://blog.pearltechnology.com/use-of-transactionscope-in-net-2/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed</link>
		<comments>http://blog.pearltechnology.com/use-of-transactionscope-in-net-2/#comments</comments>
		<pubDate>Wed, 26 Aug 2009 12:53:50 +0000</pubDate>
		<dc:creator>Geer</dc:creator>
				<category><![CDATA[Application Development]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[MSDTC]]></category>
		<category><![CDATA[TransactionScope]]></category>

		<guid isPermaLink="false">http://blog.pearltechnology.com/?p=79</guid>
		<description><![CDATA[In one of the projects I’m currently working on, I have to handle multiple SQL operations in one transaction, so if anything goes wrong in a particular operation, things done in previous operations can be rolled back automatically.  This can be done by using Transaction in a Stored Procedure directly, but you might lose some [...]]]></description>
			<content:encoded><![CDATA[<p>In one of the projects I’m currently working on, I have to handle multiple SQL operations in one transaction, so if anything goes wrong in a particular operation, things done in previous operations can be rolled back automatically.  This can be done by using Transaction in a Stored Procedure directly, but you might lose some flexibility that way.  For example, when you want to insert an object with multiple children in database, it’s not easy to pass an array or a list of items (children object) to the Stored Procedure.  So, I considered using TransactionScope provided by .NET to handle this.</p>
<p>In order to get away from code being escalated to MSDTC (Microsoft Distributed Transaction Coordinator), I decided to use single SqlConnection per TransactionScope.  Also, to maximize code reusability, we ended up with the following development pattern.  For simplicity reason, error handling is not added in the example below.</p>
<pre style="font-family:Courier New;line-height:14px"><span style="color:blue">public</span> <span style="color:blue">static</span> <span style="color:blue">void</span> CreateOrder(<span style="color:#006080">Order</span> myOrder)
{
    <span style="color:blue">using</span> (<span style="color:#006080">TransactionScope</span> scope =
            <span style="color:blue">new</span> <span style="color:#006080">TransactionScope</span>(<span style="color:#006080">TransactionScopeOption</span>.RequiresNew))
    {
        <span style="color:blue">using</span> (<span style="color:#006080">SqlConnection</span> cn = <span style="color:#006080">DB</span>.GetConnection())
        {
            cn.Open();
            <span style="color:#006080">SqlCommand</span> cmd = <span style="color:blue">new</span> <span style="color:#006080">SqlCommand</span>();
            cmd.Connection = cn;

            InsertOrderTransaction(myOrder, cmd);
        }
        scope.Complete();
    }
}

<span style="color:blue">internal</span> <span style="color:blue">static</span> <span style="color:blue">void</span> InsertOrderTransaction(<span style="color:#006080">Order</span> myOrder, <span style="color:#006080">SqlCommand</span> cmd)
{
    cmd.CommandText = "dbo.spCOrder";
    cmd.<span style="color:#006080">CommandType</span> = <span style="color:#006080">CommandType</span>.StoredProcedure;

    cmd.Parameters.Clear();
    cmd.Parameters.AddWithValue("@CustomerID", myOrder.CustomerID);
    <span style="color:green">// ...</span>

    myOrder.ID = <span style="color:#006080">Convert</span>.ToInt64(cmd.ExecuteScalar());

    InsertOrderTransactionPostProcessing(myOrder, cmd);
}</pre>
<p>As you can see, the method InsertOrderTransaction takes the Order object and a SqlCommand instance. It assumes that the SqlConnection has been established for the SqlCommand in the calling method. It doesn’t care if the SqlCommand needs to be executed within a transaction or not. It simply executes a SQL statement or a Stored Procedure. In its calling method CreateOrder, it defines the TransactionScope and defines and opens a SqlConnection. It can call multiple transactional methods (in this case InsertTransaction) and keep them all in one transaction. However, you don’t have to define a TranscationScope in the calling method if you are not dealing with multiple SQL operations. You can also add pre-processing and post-processing functions if needed.</p>
<pre style="font-family:Courier New;line-height:14px"><span style="color:blue">internal</span> <span style="color:blue">static</span> <span style="color:blue">void</span> InsertOrderTransactionPostProcessing(<span style="color:#006080">Order</span> myOrder, <span style="color:#006080">SqlCommand</span> cmd)
{
    <span style="color: #0000ff">if</span> (myOrder.OrderItems != <span style="color:blue">null</span>)
    {
        <span style="color: #0000ff">foreach </span>(<span style="color:#006080">OrderItem</span> myItem<span style="color:blue"> in </span>myOrder.OrderItems)
        {
            myItem.OrderID = myOrder.ID;
            InsertOrderItemTransaction(myItem, cmd);
        }
    }
}

<span style="color:blue">internal</span> <span style="color:blue">static</span> <span style="color:blue">void</span> InsertOrderItemTransaction(<span style="color:#006080">OrderItem</span> myItem, <span style="color:#006080">SqlCommand</span> cmd)
{
    cmd.CommandText = "dbo.spCOrderItem";
    cmd.<span style="color:#006080">CommandType</span> = <span style="color:#006080">CommandType</span>.StoredProcedure;

    cmd.Parameters.Clear();
    cmd.Parameters.AddWithValue("@ItemID", myItem.ItemID);
    <span style="color:green">// ...</span>
    myItem.OrderItemID = <span style="color:#006080">Convert</span>.ToInt64(cmd.ExecuteScalar());
}</pre>
<p>One thing you have to be aware of is that TransactionScope may not be a good choice if these operations take too long to complete. The reason is obvious. Transaction may result in temporary locking on certain objects (such as tables) in your database. If the transaction needs 5 minutes to complete, it may lock a table for that long and your users may be unable to access data in the table for that long. If anything goes wrong at the very last second in the transaction, it may take another 5 minutes for the database to roll back previous operations in this transaction, and make the table inaccessible to your users for even longer. So in cases like this, one transaction may need to be broken into multiple segments.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.pearltechnology.com/use-of-transactionscope-in-net-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
