<?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>davedolan.com &#187; General Programming</title>
	<atom:link href="http://davedolan.com/blog/?feed=rss2&#038;cat=4" rel="self" type="application/rss+xml" />
	<link>http://davedolan.com/blog</link>
	<description>Website not included.</description>
	<lastBuildDate>Sun, 24 Jan 2010 05:46:11 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A Misadventure in (someone else&#8217;s) GoF Land</title>
		<link>http://davedolan.com/blog/?p=157</link>
		<comments>http://davedolan.com/blog/?p=157#comments</comments>
		<pubDate>Sun, 24 Jan 2010 05:18:51 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>
		<category><![CDATA[SQL Code]]></category>
		<category><![CDATA[GoF]]></category>
		<category><![CDATA[Patterns]]></category>
		<category><![CDATA[WTF]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=157</guid>
		<description><![CDATA[It's ok to decouple your design from your implementation, as long as you eventually get to the implementation.]]></description>
			<content:encoded><![CDATA[<p>So, here I go again.  I don&#8217;t want my sparsely populated blog to turn into a collection of articles from <a href="http://thedailywtf.com/">the Daily WTF</a>, but I do want to use a real world example, with the names changed to protect the innocent and guilty, to illustrate a point.  </p>
<p>Design patterns, object oriented design, and the employment thereof can be just as much a cure in search of a disease as they are a cure for a disease.  I&#8217;ve recently run into this lock, stock, and barrel in a project with my unnamed employer.</p>
<p>There is this project, let&#8217;s call it FLEA, which is a relatively straightforward web forms application. Written as a front end to handle some day to day process for a particular customer, it was made out to be some kind of shimmering example of, well what the architect might have said &#8220;Stuff I read on the back cover of a book in the lavatory.&#8221;  </p>
<p>It had &#8220;everything&#8221; from service locators, coding against interfaces, and perhaps most glaringly, a monstrous construct that was referred to as &#8220;The Repository Pattern on steroids.&#8221; </p>
<p>It&#8217;s one thing to permit reuse of code by decoupling interface from implementation, but it&#8217;s quite another to hobble the developer by only making available interfaces that operate on fully populated domain objects.</p>
<p>I saw places where they would set a flag in a table record by loading an object, all of it&#8217;s sub-objects, and sub-objects, with carefully constructed IF-THEN logic to subvert graph loops, then set &#8216;myPerson.Disabled = true;  PersonRepository.Save(myPerson);&#8217;.  Now its fine if you present that interface, then  detect that only the Disabled flag changed, and update just that, but what I found was quite another beast:  It proceeded to delete half of the sub-objects, re-add them, then ignore the rest of them, and do a multi-table update of the full object (without using a join, anywhere in the logic) creating a new database connection for every other call.  Needless to say, this worked brilliantly when the thing only loaded 2 or 3 master objects but when it was scaled to include ten thousand users, disabling a user, and I use this phrase QUITE LITERALLY sent the server out to lunch.  You could go to the corner store and back before it finished running a top-down depth loop of connection grabbing calls to update stuff.</p>
<p>It&#8217;s still not probably quite clear the degree of repository extremism I&#8217;m talking about here:</p>
<p>We had:<br />
PersonRepository (with methods to GetAll, GetByLocation, GetById, Update, and Delete)<br />
PersonLocationRepository (which was called repeatedly for every person loaded, even when displaying them in a dialog box, to avoid having to learn what a join is.)<br />
PersonLocationActivityRepository<br />
ActivityRepository<br />
PlacesRepository<br />
PersonEthnicityRepositiry<br />
PersonJobCodeRepository<br />
PersonHRRecordRepository<br />
PersonMotherInLawRepository (Ok, I&#8217;m making that up.)<br />
plus about 20 more (not exaggerating, I swear.)</p>
<p>That variety alone is not a problem. But calling LoadPerson or whatever the actual routine was called invoked a service locator, which loaded a bunch of other things, which called a service layer, which called a business logic layer, which then loaded a repository, which loaded a DAL object for each one of these things, DEEP. So that loading a person ended up instantiating a generic service loader factory, which created a service layer factory, and then proceeded to call a business logic layer factory, to create a DAL factory, and eventually instantiate a DAL object, to read the ethinicity of a person. Then all of those were destroyed, and the PersonHrRecord was loaded with a new chain of the same stuff.  </p>
<p>Loading the user administration page literally kicked off 300,000 database connections, and called half a million stored procedures, loaded ALL of the data client side, and filtered out the results with fancy anonymous method calls to IList enumerators.  And just because they realized what a hulking mess this was on the database, all of the results were chucked into ViewState, which to save time was chucked into the Session.</p>
<p>I, along with two others, retooled the entire project using Linq To SQL in about a month of half time working on this, but wow it was amazing.  </p>
<p>If it would have been a well crafted joke, it would have been too meticulously executed to be even considered funny.</p>
<p>My conclusion is that it&#8217;s actually bad because of the way they made the database calls. Not the patterns themselves. There was also a demonstrable lack of understanding of what the implications of iteratively looping and loading are for performance.</p>
<p>The theory, I was told, was to make it reusable.  From a design perspective, it looked like they might have been able to do that, but when I looked at what the actual layers were doing, apart from what they looked like in UML diagrams, MAN was it a mess. </p>
<p>Put another way, it&#8217;s one thing to design your application for reusablity, but quite another to implement it in the same spirit.  At the outset of the project, it probably was originally, long ago, in a galaxy far away, a good idea to design a service layer separate from business logic layer, and a DAL layer, etc.  But to just stop there and make the rest &#8216;work somehow&#8217; without concern for the consequences of the ways the data actually got into the bottom bits.. and the way that it was unfiltered until the top bits, that was just silly.  Of course I shouldn&#8217;t blame the pattern, but if they hadn&#8217;t been aiming for that methodology, as opposed to the operations that they were actually performing underneath it, it might have been a better ending.  </p>
<p>Sure it&#8217;s common to say &#8216;That&#8217;s just an implementation detail&#8217; when you&#8217;re designing, and scoff it at for a while until it comes time to implement it, but holy crap, when it comes time to implement it, all you HAVE are the implementation details.  At that point they not only deserve SOME attention, but ALL of it.</p>
<p>This is the difficulty with GoF: Pretty Conceptual Pictures. People think they understand these, and it gives them the confidence to go implement this stuff without learning the other fundamentals.  Like, well, SQL.    (I&#8217;ve actually heard things like &#8220;I&#8217;m a C# developer, I don&#8217;t really DO SQL!&#8221; If I had my way, I&#8217;d put them in a corner with a command line OSQL.exe tool for the next three months and not let them come back until they&#8217;d gone through Books Online from top to bottom three times after that statement.) Pretty pictures like this also make it easy to gloss over an actual lack of planning on the bottom so that management doesn&#8217;t know they&#8217;ve bought into a dud until the delivered app kills the clients database farm.</p>
<p>The goal of an application is to have it work.  Whatever abstractions you put on it to make it &#8216;easier to develop&#8217; are not billable features to the client.  You do not get extra line items on the proposal for Service Locator Patterns, and certainly that&#8217;s not a justification for screwing up the actual project. </p>
<p><strong>Customer&#8217;s Boss:</strong> &#8220;This thing is a piece of crap, it kills our servers!&#8221;<br />
<strong>Developer:</strong> &#8220;But it was completely decoupled from the implementation!&#8221;<br />
<strong>Customer&#8217;s Boss</strong>: &#8220;Oh, right, sorry, I guess you did actually deliver what we ordered. I&#8217;m glad you know what you&#8217;re doing when it comes to object oriented design. So many people focus solely on the final product, without so much as a thought devoted to the design process. Clearly you have attended one of our finest higher educational institutions to know such things. And besides, I didn&#8217;t realize you were a SENIOR developer, I should be yelling at a grunt code right now. You shouldn&#8217;t be troubled with implementation details.&#8221;<br />
<strong>Developers Boss:</strong> &#8220;I smell a RAISE for one of our brightest SENIOR developers!&#8221;<br />
<strong>Developer</strong>: Nancy Kerrigan and I are going to Disney Land!<br />
<br/></p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&amp;p=157</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Parameterizable SharePoint SqlQueryWebPart</title>
		<link>http://davedolan.com/blog/?p=113</link>
		<comments>http://davedolan.com/blog/?p=113#comments</comments>
		<pubDate>Wed, 20 May 2009 21:22:39 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>
		<category><![CDATA[General Programming]]></category>
		<category><![CDATA[SQL Code]]></category>
		<category><![CDATA[SharePoint WebPart SQL Query GridView ASP.NET]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=113</guid>
		<description><![CDATA[I&#8217;ve been so frustrated with the lack of a flexible way to just display the output of a raw SQL Query via SharePoint so I wrote one.  
At first I thought I didn&#8217;t need parameters, but I was wrong.  Everyone needs parameters, or else it&#8217;s not all that useful.  Of course, that [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been so frustrated with the lack of a flexible way to just display the output of a raw SQL Query via SharePoint so I wrote one.  </p>
<p>At first I thought I didn&#8217;t need parameters, but I was wrong.  Everyone needs parameters, or else it&#8217;s not all that useful.  Of course, that doesn&#8217;t mean you can&#8217;t still do parameterization correctly.  So I took this lemon-like opportunity to demonstrate how to [make lemonade and...]</p>
<ul>
<li> Write Web Parts for WSS3 </li>
<li> Integrate a Parameterizable SQL Query (with a few security caveats I&#8217;ll readily admit, but injectibility isn&#8217;t likely one of them, more on this in a bit) with an in-page GridView and show the output </li>
<li> How to hook it up to the Form web part using the standard SharePoint IWebPartRow interface.  </li>
</ul>
<p>First thing is first, to run a web part that hits a SQL server directly, you need Medium Trust, or to have modified your policy file to allow Sql Query permissions in your SharePoint environment.  </p>
<p>Not far after first thing is the second thing, which I&#8217;ll discuss now (second.) I&#8217;m using the non-sharepoint style web part, otherwise known as ASP.NET web part (<a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.webparts.webpart.aspx">System.Web.UI.WebControls.WebParts.WebPart</a>) as the base class for my part.   </p>
<p><strong>C#</strong></p>
<div class="code">
<code><br />
&nbsp;&nbsp;&nbsp;&nbsp;[Guid(&quot;7fd6fa72-9214-4cf0-b30b-ef7d931261cb&quot;)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;public class SqlQueryWebPart : System.Web.UI.WebControls.WebParts.WebPart {<br />
</code>
</div>
<p>Why have I done this?  Becaue it&#8217;s the new recommended best practice from the kids at Microsoft who built it.  If you need SharePoint, you can get it with a wink, a nod, and the SharePoint Object Model.</p>
<p>I have the Query string, the connection stuff, the authentication type, and probably a few other doodads I forgot to mention as web part parameters.  (If you look at my code, the Sorting stuff is all commented out cause I kept screwing it up, and I felt that I didn&#8217;t really want to mess with it anymore for the time being.  The web part works without it.)  The reason I&#8217;m bothering to show you on the page here is to point out a few things, the Attributes with which we adorn the properties are slightly different than those of the SharePoint web parts variety of them you might know from WSS V2.  </p>
<p><a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.webparts.personalizableattribute.aspx">Personalizable</a> means that it will be serialized and stored as a parameter and re-populated after the part is instantiated.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.webparts.webbrowsableattribute.aspx">WebBrowsable</a> means that it will genearate an editor field in the Default Editor Part (These were formerly known as ToolParts in the old model,) when you go in to configure the web part.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.webparts.webdisplaynameattribute(VS.80).aspx">WebDisplayName</a> just means &#8220;This is what we&#8217;ll label it in the Default Editor Part&#8221;.</p>
<p><a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.categoryattribute.aspx">Category</a> is short for &#8220;The name of the collapsable section under which it appears in the default Editor Part.&#8221;</p>
<p><strong>C#</strong></p>
<div class="code">
<code><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Personalizable(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebBrowsable(true),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebDisplayName(&quot;Grid Lines&quot;),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Category(&quot;Query Details&quot;)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public GridLines GridLineConfig {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return m_GridLines;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_GridLines = value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} private GridLines m_GridLines = GridLines.Both;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Personalizable(), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebBrowsable(true),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebDisplayName(&quot;Server Name&quot;),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Category(&quot;Query Details&quot;)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string ServerName {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return m_hostName; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_hostName = value; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} private string m_hostName = string.Empty;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Personalizable(), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebBrowsable(true),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebDisplayName(&quot;Database Name&quot;), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Category(&quot;Query Details&quot;)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string DatabaseName {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return m_dbName; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_dbName = value; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} private string m_dbName = string.Empty;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[DefaultValue(AuthType.SQL),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Personalizable(), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebBrowsable(true),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebDisplayName(&quot;Authentication&quot;), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Category(&quot;Query Details&quot;)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public AuthType AuthentictionMethod {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get { return m_AuthType; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set { m_AuthType = value; }<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} private AuthType m_AuthType = AuthType.Windows; <br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Personalizable(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebBrowsable(true),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebDisplayName(&quot;User Id&quot;),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Category(&quot;Query Details&quot;)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string UserName {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return m_loginUser; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_loginUser = value; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} private string m_loginUser = string.Empty;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Personalizable(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebBrowsable(true),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebDisplayName(&quot;Password&quot;),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Category(&quot;Query Details&quot;)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string Password {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get { return m_MaskedPassword; }<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set { m_MaskedPassword = value; }<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} private string m_MaskedPassword = string.Empty;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Personalizable(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebBrowsable(false)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string InnerPassword {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get { return m_PrivatePassword; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set { m_PrivatePassword = value; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} private string m_PrivatePassword = string.Empty;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Personalizable(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebBrowsable(true),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebDisplayName(&quot;Select Query&quot;),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Category(&quot;Query Details&quot;)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public string SQLQuery {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return m_QueryText; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_QueryText = value; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} private string m_QueryText = string.Empty;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Personalizable(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebBrowsable(true),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebDisplayName(&quot;Page Size&quot;),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Category(&quot;Query Details&quot;)]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public int PageSize {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return m_PageSize; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_PageSize = value; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} private int m_PageSize = 10;<br />
</code>
</div>
<p>Now, for the security caveats: I&#8217;ll tell you that it&#8217;s a little dangerous to put the Sql username and password in your web part instances configuration properties, cause if someone decides to export it, then you can see the username and password; but this does not apply if you use the Windows authentication mode.  So, you figure out whether or not you can work around the issues.</p>
<p>As for the Parameterization: </p>
<p>I extract the expected parameters, as specified in the web part property, using a string-through, ie, I jump through the string one character at a time, looking for the parameters.  This means I get them all in one pass, instead of a bunch of regexes or finds and splits, etc.  They then go into a list, which is the list of expected &#8216;named paramters&#8217; coming from the connected web parts.  If I don&#8217;t get a match between the ones that are in your query and the ones connected to me, then I display a message.</p>
<p><strong>C#</strong></p>
<div class="code">
<code><br />
private void ExtractExpectedParameters(string p) {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_expectedParams = new List&lt;string&gt;();<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool collecting = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder sb = new StringBuilder();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (int x = 0; x &lt; p.Length; x++) {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char c = p[x];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (collecting) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool dropOut = false;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (x == (p.Length - 1)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.Append(c);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dropOut = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!char.IsLetterOrDigit(c) || dropOut) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;collecting = false;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// found a parameter name<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_expectedParams.Add(sb.ToString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb = new StringBuilder();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sb.Append(c);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!collecting &amp;&amp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c == &#039;@&#039;) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;collecting = true;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_HasParameters = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</code>
</div>
<p>So, after I set the fact that I have some parameters, I have to know when to read the values, and after much tribulation, and reference perusal, I have discovered that the time to suck the data from your producing source is OnPreRender:</p>
<p><strong>C#</strong></p>
<div class="code">
<code><br />
protected override void OnPreRender(EventArgs e) {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// parse the SQL and rip out what we&#039;re looking for. Also set m_HasParameters<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExtractExpectedParameters(this.SQLQuery);<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bool canQuery = false;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_HasParameters) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_provider != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_provider.GetRowData(new RowCallback(GetRowData));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;canQuery = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;canQuery = true;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EnsureChildControls();<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_CmdParameters = new Dictionary&lt;string, object&gt;();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// we don&#039;t want to run any query unless we have all the right params and stuff.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( m_HasParameters &amp;&amp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_provider != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PropertyDescriptorCollection props = m_provider.Schema;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (props != null &amp;&amp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.Count &gt; 0 &amp;&amp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;props.Count == m_expectedParams.Count &amp;&amp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_tableData != null &amp;&amp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_tableData.Row != null &amp;&amp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_tableData.Row.ItemArray != null &amp;&amp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_tableData.Row.ItemArray.Length == m_expectedParams.Count) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach (PropertyDescriptor prop in props) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.m_CmdParameters.Add(prop.Name, m_tableData.Row[prop.Name]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;canQuery = true;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registerError(string.Format(&quot;Supply required parameters before results can be displayed. Expecting: {0}.&quot;, string.Join(&quot;,&quot;, m_expectedParams.ToArray())));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_HasParameters) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registerError(string.Format(&quot;Based on the specified query, one or more parameter(s) are required. &lt;/br&gt; Please connect this web part to a Form Web Part to obtain the required input parater(s): {0}.&quot;, string.Join(&quot;,&quot;, m_expectedParams.ToArray())));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (canQuery) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RetreiveData();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RebindGrid();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;base.OnPreRender(e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</code></p>
<div style="width:100%; background-color:silver; text-indent: 25px; text-decoration: italic;">
   Note about catching exceptions:  In this situation, I&#8217;ve decided to catch this error and display the output on the screen, so I don&#8217;t let it get through.  This is with the intention of allowing one to not only know that something broke, but to help fix it without bringing down the entire process.  If you are really concerned, you can do what I have done in the query results bit and only display the error text to admins, but I display the query parameter errors to everyone for the sake of helping the poor user who is hooking this up on their MySite (or wherever else some newbie to SharePoint, but not to SQL, might try it) trying to make sense of the idea of connected web parts.  If you use my part, you can change that before deploying it<a href="http://zerohedge.com">.</a> I&#8217;m fully aware that under most circumstances one does not want to catch and hold an exception. But in this case, I feel that it is warranted.
</div>
<p><br/><br />
<br/></p>
<p>Finally, the coup de gras is to actually perform the parameterized query. No biggity now.</p>
<p><strong>C#</strong><br />
<code><br />
private void RetreiveData() {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SqlConnection oConn = null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_MaskedPassword != passowrdMask) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InnerPassword = m_MaskedPassword;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_MaskedPassword = passowrdMask;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_AuthType == AuthType.SQL) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_connectionString = string.Format(&quot;Data Source={0};Initial Catalog={1};User Id={2};Password={3};Persist Security Info=false&quot;, m_hostName, m_dbName, m_loginUser, m_PrivatePassword);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_connectionString = string.Format(&quot;Data Source={0};Initial Catalog={1};Integrated Security=SSPI&quot;, m_hostName, m_dbName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oConn = new SqlConnection(m_connectionString);<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oConn.Open();<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;using (SqlCommand cmd = oConn.CreateCommand()) {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.CommandText = this.m_QueryText;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.CommandType = CommandType.Text;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_HasParameters) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//do parameters!<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach (String s in m_CmdParameters.Keys) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!string.IsNullOrEmpty(m_CmdParameters[s].ToString())) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.Parameters.AddWithValue(&quot;@&quot; + s, m_CmdParameters[s]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!m_HasParameters ||<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cmd.Parameters.Count == m_CmdParameters.Count) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SqlDataReader dr = cmd.ExecuteReader();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt = new DataTable();<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dt.Load(dr);<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (m_HasParameters) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registerError(string.Format(&quot;Supply required parameters before results can be displayed. Expecting: {0}.&quot;, string.Join(&quot;,&quot;, m_expectedParams.ToArray())));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;catch (Exception ex) {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// this is a Smart Error Handler, in that it shows you a generic message<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// if you&#039;re a Schmoe and a Detailed description if you&#039;re a site collection admin.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SPUser usr = SPContext.GetContext(this.Context).Web.CurrentUser;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (usr.IsSiteAdmin) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registerError(string.Format(&quot;{0}: {1} &lt;p style=\&quot;font-weight:bold;\&quot;&gt;{2}&lt;/p&gt;&lt;p&gt;Connection String = {3}&quot;, ex.GetType().Name, ex.Message, ex.StackTrace, m_connectionString));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;registerError(&quot;Error loading SqlQuery Web Part. Please contact your administrator.&quot;);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;finally {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (oConn != null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oConn.Dispose();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</code>
</div>
<p>This is a rough model of the web part, and in need of a bit of refactoring to remove some duplication, but you get the idea.  I hope.</p>
<p>Attached is the code files/project for VS 2008.  <a href="http://davedolan.com/downloads/SqlQueryPart.zip">Click to Download it</a>.  I&#8217;ve decided, after considering it carefully that I will let you have the wsp already built. No warranty. If you don&#8217;t understand how it works, you can ask, and I&#8217;ll try to answer. And NO, I won&#8217;t customize it for your needs, nor will I change it to do something else &#8212; with one exception: if you figure out a way to fix the paging junk then I&#8217;ll put your fix in and give you credit. (Yes I could do it eventually, but I don&#8217;t want to mess with it right now!)  So, <a href="http://davedolan.com/downloads/SqlQueryPart.wsp">here</a> have at it!</p>
<p><em>Late Breaking edit: The code provided here has been fixed now that I got my real version from the source control. I&#8217;ve corrected the problem with the &#8216;default values&#8217;.</em></p>
<p>(PS: Use <a href="http://community.bamboosolutions.com/blogs/bambooteamblog/archive/2008/05/21/how-to-install-windows-sharepoint-services-3-0-sp1-on-vista-x64-x86.aspx">WSSOnVista from BambooSolutions.com </a>to install SharePoint on your development Vista host and run/test/debug without remote desktop etc.)</p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&amp;p=113</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ok, I promised a better LINQ example..</title>
		<link>http://davedolan.com/blog/?p=90</link>
		<comments>http://davedolan.com/blog/?p=90#comments</comments>
		<pubDate>Thu, 14 Aug 2008 06:40:50 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>
		<category><![CDATA[SQL Code]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=90</guid>
		<description><![CDATA[So, I made one, except I posted it on CodeProject instead of this blog.  I figured with this thing I wanted to get a lot of people in the audience. Not to mention that makes free advertising for me and my blog anyway.
]]></description>
			<content:encoded><![CDATA[<p>So, I made one, except I posted it on <a href="http://www.codeproject.com/KB/linq/LINQDynamicPredicate.aspx">CodeProject</a> instead of this blog.  I figured with this thing I wanted to get a lot of people in the audience. Not to mention that makes free advertising for me and my blog anyway.</p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&amp;p=90</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Down the rabbit hole with LINQ-to-SQL.</title>
		<link>http://davedolan.com/blog/?p=88</link>
		<comments>http://davedolan.com/blog/?p=88#comments</comments>
		<pubDate>Fri, 18 Jul 2008 05:48:35 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[.NET Coding]]></category>
		<category><![CDATA[SQL Code]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[3.5]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[LINQ]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/?p=88</guid>
		<description><![CDATA[Man, just when I thought I was starting to get the hang of LINQ-to-SQL and knowing what kind of cool features it has, I ran into some interesting problems.  For one the DataContext needs to have an &#8216;appropriate lifetime&#8217; which means you have to play around with it, there aren&#8217;t real standards.  The [...]]]></description>
			<content:encoded><![CDATA[<p>Man, just when I thought I was starting to get the hang of LINQ-to-SQL and knowing what kind of cool features it has, I ran into some interesting problems.  For one the DataContext needs to have an &#8216;appropriate lifetime&#8217; which means you have to play around with it, there aren&#8217;t real standards.  The issue of context lifetime manifests itself when you try to use LINQ-to-SQL as a middle tier application brick of sorts to toss objects into back and from the db &#8212; you get duplicate key conflicts when you try to .Attach() and object to update, so you basically have to kill the context to avoid that. How crazy is that?  For example, on a web page, (aspx) I use a single datacontext, and I tried caching it in the HttpContext.Application[] scope but I kept getting errors basically pointing to staleness of the primary keys (saying duplicate key exists, etc&#8230;)</p>
<p>I&#8217;m going to go over two things on this context lifetime issue: A) What the problem is, exactly, and B) what I did to fix it in my Webpage example.</p>
<p>Part I: The problem</p>
<p>    The idea of the DataContext in LINQ is that it tracks changes for you.  Like a fancy living Dataset.  You put objects into it, and holds state that represents whether or not you&#8217;ve changed something since it was read from the db, and when you call .SubmitChanges() you get them all committed.  The problem with this is that the context object HOLDS A REFERNCE to all of the objects it&#8217;s ever touched since it&#8217;s instantiation.  That&#8217;s an issue when you&#8217;re trying to say&#8230; change and object, or attach an object that you&#8217;ve constructed from serialization, but has the same primary key as another that&#8217;s already in there&#8230;  So what to do? Squash the whole context after a quick call to SubmitChanges();</p>
<p>Part II: The solution (That I used.)</p>
<p>    The last sentence of the last paragraph of &#8216;the problem&#8217; alludes to the fact taht I squash the context; however, it doesn&#8217;t say how I hook on that in an aspx app.  I <a href="http://blogs.msdn.com/dinesh.kulkarni/archive/2008/04/27/lifetime-of-a-linq-to-sql-datacontext.aspx">read around and found a suggestion</a> that I try out a Request-Scoped context.  How might one do this?</p>
<p>Global.asax!  You add two handlers:</p>
<div class="code">
<code><br />
&nbsp;<br />
void Application_BeginRequest(object sender, EventArgs args)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//create the context<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MyDataContext ctx = new MyDataContext();<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// gotcha now, for the whole duration of the request (Context.Items lives for One (1) request!)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpContext.Current.Items[&quot;DataContextStorage&quot;] = ctx;<br />
&nbsp;<br />
}<br />
&nbsp;<br />
void Application_EndRequest(object sender, EventArgs args)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp; MyDataContext o =&nbsp;&nbsp;HttpContext.Current.Items[&quot;DataContextStorage&quot;] as MyDataContext;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // say goodbye! Properly<br />
&nbsp;&nbsp;&nbsp;&nbsp; if(o != null)<br />
&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o.Dispose();<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
}<br />
</code>
</div>
<p>So How do I Access this easily?  Wrap it up!</p>
<div class="code">
<code><br />
&nbsp;<br />
public static class Config<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static MyDataContext GetCurrentDataContext()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return HttpContext.Current.Items[&quot;DataContextStorage&quot;] as MyDataContext;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;<br />
}<br />
&nbsp;<br />
</code>
</div>
<div class="code">
<code><br />
&nbsp;<br />
// DO NOT USE THE IDISPOSABLE PATTERN HERE OR ELSE!<br />
var MyContext = Config.GetCurrentDataContext();<br />
&nbsp;<br />
var Foozles&nbsp;&nbsp;= MyContext.Foobars.Where(a =&gt; a.FoobarId &lt; 1000);<br />
&nbsp;<br />
</code>
</div>
<p>Ok, so that was a minor &#8216;problem&#8217; but really just a poor understanding of the technology on my part.  I know better now, I think.</p>
<p>There&#8217;s something better that LINQ-to-SQL does, or rather, it&#8217;s a lot SEXIER in programming terms.  Since you can &#8216;where&#8217; expression your way through life with a lambda, it sure as heck makes it simple to Where your way to dynamic SQL queries generated by something simple in the UI (like a query builder interface.)  I have a perfectly great example, but rather than try and write and claim it myself, I&#8217;ll give you the source that I got, and perhaps develop a more familiar and complete example later on in another post:  <a href="http://www.albahari.com/nutshell/predicatebuilder.html">C# 3.0 In a Nutshell (book website &#8216;excerpt&#8217;)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&amp;p=88</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>VBScript to Remap your Outlook Profiles to a new server.</title>
		<link>http://davedolan.com/blog/?p=83</link>
		<comments>http://davedolan.com/blog/?p=83#comments</comments>
		<pubDate>Wed, 16 Apr 2008 17:45:44 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[General Programming]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/2008/04/16/vbscript-to-remap-your-outlook-profiles-to-a-new-server/</guid>
		<description><![CDATA[Recently recovered from an incident involving the slow and painful death of a MS Exchange Server. Right smack in the middle of the day, with some 800 mailboxes on that one host.  We restored the mail stores to another Exchange Server, and ran a hack script to go and correct the homeMDB, homeMTA, and [...]]]></description>
			<content:encoded><![CDATA[<p>Recently recovered from an incident involving the slow and painful death of a MS Exchange Server. Right smack in the middle of the day, with some 800 mailboxes on that one host.  We restored the mail stores to another Exchange Server, and ran a hack script to go and correct the homeMDB, homeMTA, and msExchMailServer attributes in the AD to point to the new host. That was the easy part. Then we had all these users with outlook profiles pointing to a dead server.  Outlook may be resilient in picking the right server when you point it to the wrong server, but if the wrong server (to which is is pointed) is not available &#8211; as in if the server it&#8217;s pointed at is DEAD, then it doesn&#8217;t know to get the new info from the AD to point you to the correct one.  This, of course, is exactly what happened to me an my ilk.  We had some hundreds of users without profiles pointing to the right host.  You&#8217;ve heard of Autoconfig for Outlook 2007, but that only works for NEW profiles, not existing ones suddenly pointing to a dead host.  So what to do?  Manually have all the users repoint their profiles by talking them through the Mail Control Panel widgets?  NO! That&#8217;s expensive.  Instead, write a script and deploy it as a login script.  </p>
<p>Why a Login script? Well, because this script affects the HKEY_CURRENT_USER registry hive which only exists for a particular user when that user is logged on.    At least for all intents and purposes that&#8217;s true. I think it may be possible to somehow enumerate all users on the HKEY_USERS hive, but I didn&#8217;t go that far. I apologize up front for not going the extra mile on this one, but hey, look! A free script.</p>
<p>NOTE: If you copy and paste it, and get a compile error, check for abberant the new-line characters caused by the squishing of my code by the text rendering on the page.</p>
<div class="code">
<code><br />
&#039;&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--<br />
&#039;Script RepointProfile.vbs<br />
&#039;Author: Dave Dolan<br />
&#039;Purpose: Repoints exchange profiles to use NewServer instead of OldServer<br />
&#039;&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--<br />
&#039;(Editable Constants) Change OldServer and NewServer below as appropirate for the task<br />
&#039;&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-<br />
CONST OldServer = &quot;OldMailHostName&quot;<br />
CONST NewServer = &quot;NewMailHostName&quot;<br />
&#039;&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-<br />
&#039; Command Line Usage:<br />
&#039;&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--<br />
&#039; RepointProfile.vbs [/print:true|false]<br />
&#039; &#45;- (optional) print parameter when set to &#039;true&#039; displays what it&#039;s doing, otherwise it prints nothing<br />
&#039; &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--<br />
&#039; NOTE: VERY IMPORTANT: Run this in the context of the current user to change the profile settings,<br />
&#039;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; since it affects HKEY_CURRENT_USER!<br />
&#039;&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-<br />
&nbsp;<br />
&#039;&#45;&#45;-&#45;&#45;-&#45;&#45;- Edit NOTHING Below this line &#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-<br />
&nbsp;<br />
&#039;if they have non-exchange profiles, they&#039;re gonna throw (harmless if skipped) errors. I care not.<br />
on error resume next <br />
&nbsp;<br />
CONST NetBiosValue = &quot;001e6602&quot;<br />
CONST FQDNValue = &quot;001e6608&quot;<br />
CONST xFiveHundredValue = &quot;001e6612&quot;<br />
&nbsp;<br />
Const HKEY_CURRENT_USER = &amp;H80000001<br />
printParam = Wscript.Arguments.Named(&quot;print&quot;)<br />
&nbsp;<br />
if len(printParam) &gt;= 0 then<br />
&nbsp;&nbsp;if ucase(printParam) = &quot;TRUE&quot; then <br />
&nbsp;&nbsp;&nbsp;&nbsp; printValues = 1<br />
&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp; printValues = 0<br />
&nbsp;&nbsp;end if<br />
else<br />
&nbsp;&nbsp;printValues = 0<br />
end if<br />
&nbsp;<br />
computerName = &quot;.&quot;<br />
&nbsp;<br />
const BASE_KEY = &quot;Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles&quot;<br />
&nbsp;<br />
set objReg = GetObject(&quot;winmgmts:{impersonationLevel=impersonate}!\\&quot; &amp; computerName &amp; &quot;\root\default:StdRegProv&quot;)<br />
&nbsp;<br />
objReg.EnumKey HKEY_CURRENT_USER, BASE_KEY, arrSubKeys<br />
&nbsp;<br />
for each subkey in arrSubKeys<br />
&nbsp;<br />
if printValues = 1 then<br />
&nbsp;&nbsp;Wscript.Echo &quot;Subkey = &quot; &amp; subkey<br />
end if<br />
&nbsp;<br />
subKeyPath = BASE_KEY &amp; &quot;\&quot; &amp; subkey &amp; &quot;\&quot; &amp; &quot;13dbb0c8aa05101a9bb000aa002fc45a&quot;<br />
&nbsp;<br />
objReg.GetStringValue HKEY_CURRENT_USER, subKeyPath, NetBiosValue, nbServerName<br />
objReg.GetStringValue HKEY_CURRENT_USER, subKeyPath, FQDNValue, fqdn<br />
objReg.GetStringValue HKEY_CURRENT_USER, subKeyPath, xFiveHundredValue, X500<br />
&nbsp;<br />
fqdn = ucase(fqdn)<br />
&nbsp;<br />
if printValues = 1 then<br />
 Wscript.Echo &quot;Current Values&quot;<br />
 Wscript.Echo &quot;&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--&quot;<br />
 Wscript.Echo &quot;Netbios Value: &quot; &amp; nbServerName<br />
 Wscript.Echo &quot;FQDN Value: &quot; &amp; lcase(fqdn)<br />
 Wscript.Echo &quot;X500 Value: &quot; &amp; X500<br />
end if<br />
&nbsp;<br />
if instr(nbServerName, OldServer) then<br />
&nbsp;<br />
&nbsp;&nbsp;nbServerName = Replace(ucase(nbServerName), OldServer, NewServer)<br />
&nbsp;&nbsp;fqdn = lcase(Replace(fqdn, OldServer, NewServer))<br />
&nbsp;&nbsp;x500 = Replace(X500, OldServer, NewServer)<br />
&nbsp;<br />
&nbsp;&nbsp;objReg.SetStringValue HKEY_CURRENT_USER, subKeyPath, NetBiosValue, nbServerName<br />
&nbsp;&nbsp;objReg.SetStringValue HKEY_CURRENT_USER, subKeyPath, FQDNValue, fqdn<br />
&nbsp;&nbsp;objReg.SetStringValue HKEY_CURRENT_USER, subKeyPath, xFiveHundredValue, X500<br />
&nbsp;<br />
&nbsp;&nbsp;if printValues = 1 then<br />
&nbsp;&nbsp; Wscript.Echo &quot;&quot;<br />
&nbsp;&nbsp; Wscript.Echo &quot;New Values&quot;<br />
&nbsp;&nbsp; Wscript.Echo &quot;&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;--&quot;<br />
&nbsp;&nbsp; Wscript.Echo &quot;Netbios Value: &quot; &amp; nbServerName<br />
&nbsp;&nbsp; Wscript.Echo &quot;FQDN Value: &quot; &amp; fqdn <br />
&nbsp;&nbsp; Wscript.Echo &quot;X500 Value: &quot; &amp; X500<br />
&nbsp;&nbsp;end if<br />
&nbsp;<br />
end if<br />
&nbsp;<br />
next<br />
&nbsp;<br />
set objReg = nothing<br />
&nbsp;<br />
</code>
</div>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&amp;p=83</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Quick, list the dbs and Users!</title>
		<link>http://davedolan.com/blog/?p=75</link>
		<comments>http://davedolan.com/blog/?p=75#comments</comments>
		<pubDate>Mon, 21 Jan 2008 18:21:37 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[SQL Code]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/2008/01/21/quick-list-the-dbs-and-users/</guid>
		<description><![CDATA[I’ve been orchestrating a move from an old SQL 2000 database to a SQL 2k5 DB host. Most of the dbs are in use somewhere by some application or other, and I can’t tell by looking at it just what they are. One of the things I’ll need to do is contact all of the [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been orchestrating a move from an old SQL 2000 database to a SQL 2k5 DB host. Most of the dbs are in use somewhere by some application or other, and I can’t tell by looking at it just what they are. One of the things I’ll need to do is contact all of the users of each one and ask them to tell me what the impact is, as well as inform them that they’ll need to swap a hostname out in the connection string. No problem, I can just click through all 50 databases on the host and look at all the users, and write them down, and send an email to them all asking what gives… The trouble is, half the time they have no idea what db’s are on the host, and what if any they have to do with it. I didn’t feel like spending about 4 hours on this, so I quickly tossed off a script that generates some SQL to figure out the real list, without getting too complicated here. In case you find it useful, here’s the script to generate the second script:</p>
<div class="code">
<code><br />
use master</p>
<p>&#45;- below is a query to generate a single query to get all the users for each database<br />
begin<br />
declare dbs cursor for select name from sysdatabases</p>
<p>declare @dbName VARCHAR(25)</p>
<p>open dbs</p>
<p>fetch dbs into @dbName<br />
while @@fetch_status &gt;= 0<br />
begin</p>
<p>&nbsp;&nbsp;if @dbName in (&#039;master&#039;, &#039;msdb&#039;, &#039;tempdb&#039;, &#039;pubs&#039;, &#039;model&#039;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;begin<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &#039;&#45;- skipping system db &#039; + @dbName<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;begin<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &#039;&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-&#039;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &#039;&#45;- &#039; + @dbName + &#039; &#45;-&#039;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &#039;&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-&#039;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &#039;select &#039;&#039;&#039; + @dbName + &#039;&#039;&#039; as [DB], name as [User] from &#039; + @dbName + &#039;.dbo.sysusers where hasdbaccess = 1&#039;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print &#039;union&#039;<br />
&nbsp;&nbsp;&nbsp;&nbsp;end</p>
<p>&nbsp;&nbsp;fetch next from dbs into @dbName<br />
end</p>
<p>close dbs<br />
deallocate dbs<br />
end</p>
<p>go</p>
<p></code>
</div>
<p>After that runs it will generate in the output window (or the console if you use OSQL or some other command line tool to run it,) this form of output. I pipe it to another file, and change the last ‘union’ to a ‘go’ and we’re done. I probably should have also excluded the user dbo, but I didn’t you can if you want.</p>
<div class="code">
<code><br />
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-<br />
&#45;- FirstDB &#45;-<br />
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-<br />
select &#039;FirstDB&#039; as [DB], name as [User] from FirstDB.dbo.sysusers where hasdbaccess = 1<br />
union<br />
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-<br />
&#45;- aspnetdb &#45;-<br />
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-<br />
select &#039;aspnetdb&#039; as [DB], name as [User] from aspnetdb.dbo.sysusers where hasdbaccess = 1<br />
union<br />
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-<br />
&#45;- OtherDB&#45;-<br />
&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;-&#45;&#45;&#45;-<br />
select &#039;OtherDB&#039; as [DB], name as [User] from OtherDB.dbo.sysusers where hasdbaccess = 1<br />
go &#45;- changed from union as generated by the script<br />
&#45;- this continues until all dbs are enumerated, excludes the system dbs.<br />
&nbsp;&nbsp;</code>
</div>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&amp;p=75</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rich Programmer Food: Highly recommended reading</title>
		<link>http://davedolan.com/blog/?p=74</link>
		<comments>http://davedolan.com/blog/?p=74#comments</comments>
		<pubDate>Fri, 18 Jan 2008 19:37:08 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[General Programming]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/2008/01/18/rich-programmer-food-highly-recommended-reading/</guid>
		<description><![CDATA[http://steve-yegge.blogspot.com/2007/06/rich-programmer-food.html
I have been preaching things like this for a long time, but Steve here is a bit more fluent about explaining it.  I&#8217;ll not try to turn you off to the ideas presented here by summarizing it before you read it. Honestly, it&#8217;s the perfect expression of a relatively amorphous emotion I&#8217;ve had about [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://steve-yegge.blogspot.com/2007/06/rich-programmer-food.html">http://steve-yegge.blogspot.com/2007/06/rich-programmer-food.html</a></p>
<p>I have been preaching things like this for a long time, but Steve here is a bit more fluent about explaining it.  I&#8217;ll not try to turn you off to the ideas presented here by summarizing it before you read it. Honestly, it&#8217;s the perfect expression of a relatively amorphous emotion I&#8217;ve had about compilers and their place in the world of CS for a long time, (but obviously I can&#8217;t take credit for the quality of Steve&#8217;s writing, of course.)</p>
<p>Make yourself read it though, please, if you never do another thing for me as long as you know me. (Halo_Four, if you&#8217;re reading this, this means you too.)</p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&amp;p=74</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dirty Data?</title>
		<link>http://davedolan.com/blog/?p=64</link>
		<comments>http://davedolan.com/blog/?p=64#comments</comments>
		<pubDate>Mon, 23 Jul 2007 17:42:17 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[General Programming]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/2007/07/23/dirty-data/</guid>
		<description><![CDATA[I&#8217;ve heard from all sides lately about how there is a growing problem with &#8216;Dirty Data&#8217;&#8230;
What is Dirty Data?  According to IBM, and various other folks, Dirty Data is data that is extracted from the real world that cannot be nicely integrated into relational models because it&#8217;s not organized, or doesn&#8217;t fit a particular [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve heard from all sides lately about how there is a growing problem with &#8216;Dirty Data&#8217;&#8230;</p>
<p>What is Dirty Data?  According to IBM, and various other folks, Dirty Data is data that is extracted from the real world that cannot be nicely integrated into relational models because it&#8217;s not organized, or doesn&#8217;t fit a particular model.  Luckily for us, there are various products out there to &#8216;clean it&#8217; or techniques recommended by the various database manufactures to squeeze &#8216;clean&#8217; over &#8216;dirty data.&#8217; </p>
<p>First of all, WHAT?!  Do we work for computers or do they work for us?  There is no such thing as dirty data, the fact of the matter is that if your system pukes because the data isn&#8217;t in the right format, then you&#8217;re using the wrong system to process it.  The real world isn&#8217;t just &#8216;full of dirty data,&#8217; it&#8217;s full of data, and computers are here to help us process it.  It&#8217;s completely ridiculous for the database companies to say that my data is dirty.</p>
<p>Another sore point with me is the fact that they say that performance problems can stem from &#8216;unreasonable relationship tracking.&#8217;  I want to know too many facets of my data, and it&#8217;s not &#8216;database correct&#8217; of me to want my data and to be able to eat it too, from every angle, in real time.  Pardon me, but the fact that YOUR relational database doesn&#8217;t handle this kind of scenario well doesn&#8217;t mean that my request is unreasonable.  If I want to be able to efficiently track back to the original record by any one of any number of my many to one or many to many, or one to many relationships, that&#8217;s my requirement, not your place to tell me that it&#8217;s unreasonable of me to expect that it can be done.  </p>
<p>The problem is that relational database proponents, and in particular the big three commercial implementors, are all engaging in this &#8216;you can&#8217;t do that, in real life&#8217; and &#8216;its your fault our apps are slow,&#8217; propaganda, and I won&#8217;t stand for it.</p>
<p>Just as an example, and I&#8217;m sure it&#8217;s not the only way, I&#8217;m using Relavance, an associative model engine which has none of these limitations.  </p>
<p>Even Relavance aside, or even the entire associative model aside, it&#8217;s still really stupid of any real computer scientist to think, and especially to decree that certain problems are just not to be solved using computers because they are not well suited to modern technology.  If that were the attitude that people had throughout history, then we&#8217;d still be toggling in code on the front panels of computers the size of Olympus Mons.  Microsoft may be the market leader, and Oracle and IBM may sell a lot of bits and bytes, and tow very heavy loads in the marketplace, but they are not here to tell me what is and is not possible in computer science based on their own models of the universe.</p>
<p>&lt;/rant&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&amp;p=64</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>As I said before&#8230;</title>
		<link>http://davedolan.com/blog/?p=59</link>
		<comments>http://davedolan.com/blog/?p=59#comments</comments>
		<pubDate>Tue, 01 May 2007 20:01:40 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[General Programming]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/2007/05/01/as-i-said-before/</guid>
		<description><![CDATA[I mentioned in the middle of one of my other posts that I was preparing an article on Ruby.  I sort of alluded to the fact that I&#8217;d post a link, so I suppose I&#8217;ll do that now, (although it&#8217;s more likely that you&#8217;ve come to this blog FROM the article than the other [...]]]></description>
			<content:encoded><![CDATA[<p>I mentioned in the middle of one of my other posts that I was preparing an article on Ruby.  I sort of alluded to the fact that I&#8217;d post a link, so I suppose I&#8217;ll do that now, (although it&#8217;s more likely that you&#8217;ve come to this blog FROM the article than the other way around.)  <a href="http://www.devx.com/RubySpecialReport/Article/34470">Ruby for C# Geeks (DevX.com)</a>  It&#8217;s not really all that in-depth, but just to make C# folks aware of what else is out there.</p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&amp;p=59</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Associative Model of Knowledge</title>
		<link>http://davedolan.com/blog/?p=56</link>
		<comments>http://davedolan.com/blog/?p=56#comments</comments>
		<pubDate>Tue, 10 Apr 2007 05:27:32 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[General Programming]]></category>

		<guid isPermaLink="false">http://davedolan.com/blog/2007/04/10/the-associative-model-of-knowledge/</guid>
		<description><![CDATA[Forget everything you know about storing data.  Particularly the bits about retrieving it after you&#8217;ve stored it.  I said forget it, and I know you didn&#8217;t.  So, try again, forget it.
Rather than try to start by comparing this method to what you already know how to do, I&#8217;m going to just pretend [...]]]></description>
			<content:encoded><![CDATA[<p>Forget everything you know about storing data.  Particularly the bits about retrieving it after you&#8217;ve stored it.  I said forget it, and I know you didn&#8217;t.  So, try again, forget it.</p>
<p>Rather than try to start by comparing this method to what you already know how to do, I&#8217;m going to just pretend that you&#8217;ve always wondered how to store data, and never have done it before.</p>
<p>Applications acquire data.  They also retrieve data and display it for users, or do something otherwise useful with it.  Sometimes it&#8217;s the users who give the data to the application directly. Actually that happens quite a lot.  </p>
<p>We store different bits of information in different places, and we do so for the purpose of organizing things that go together. We go to all of this bother because we&#8217;re likely to want to get them back out together.  What that means to you and me as developers is that we spend quite a lot of time thinking about the kinds of things we want to get out of the system before we go putting them in. Arguably we try to think of everything we&#8217;d like to get out of it beforehand, and that&#8217;s how we&#8217;ll know we&#8217;re done with our model â€“ when it provides us with a place and method to put everything we need to know into the storage and get it back out on demand.  We&#8217;d use this information of what we need to get out later as the basis for a &#8217;schema.&#8217; A layout of how all the data looks when it&#8217;s just sitting around waiting for someone to get it back out again.</p>
<p>Great! That sounds simple enough!  Ah, but life isn&#8217;t so forgiving, and neither is programming.  Today we think we know what we want, and that&#8217;s it, but tomorrow, that all might change.  In fact, if you ask enough pointy haired bosses about what they want from the data they&#8217;re paying you to store in a database, then you&#8217;re likely to get  a few things in common, and a bunch of special requests.  Some of what they want is &#8217;stuff&#8217; that needs to be in there, but also, they want &#8216;ways to organize things&#8217; on the way out especially.  Some people would call these differing requirements views, or reports.</p>
<p>Fine, so we can&#8217;t possibly think of all of the kinds of views and reports, so we might as well just not think about them ahead of time, right? We&#8217;ll just store everything as generally as possible while leaving some things together that obviously go together in pretty much all cases, and that way, we can let the person getting things out tell us what they want at that time, and never worry about it again.  Especially not that would push the application delivery date back! Right? WRONG!</p>
<p>When we store data, each thing we&#8217;d like to know about is called a Concept.  And all of the different aspects of the concepts are different sorts of &#8216;lights in which we&#8217;d like to view these concepts,&#8217; which we might term a Context.   So in life we have concepts, or things or ideas of interest, and contexts, which are the glasses through which we view these concepts. </p>
<p>When we want to store a concept in our knowledge store, we put it in there, and designate it to be accessible in a particular context.  Of course it&#8217;s not really friendly to the user to just pull every concept out with every time we want to retrieve information, so the idea of limiting a concept to a particular context seems to make a lot of sense.  We do this in our everyday conversation, even sometimes a single word can mean many things!  Surely that&#8217;s an idea we&#8217;d have difficulty describing in a fileâ€¦ Or is it?</p>
<p>Lucky for us, Everyone in the Universe uses Associative Knowledgebases, and everyone knows that in an associative knowledgebase, you add concepts to the base, associated with a particular context, and from there you are able to retrieve concepts relative to the particular context of reference.  You can have a single concept be availabe in as many contexts as are needed, and you don&#8217;t need to keep putting multiple representations of the same concept in over and over again to get the job done.  Each concept has a bit of data that goes with it, and it can be associated to other concepts to represent what sorts of ideas it shares with its associates.   Now an association isn&#8217;t just a one type deal, you can associate on different &#8216;axes&#8217; of association to represent different aspects of what the two concepts have in common.  Who knows, two concept items may also be associated to the same context, so when you go to retrieve information relative to a context, you&#8217;d get them both anyway!  As you may have picked up, each &#8216;concept&#8217; can be represented by a single &#8216;item&#8217; or a set of &#8216;items&#8217;, which are tiny units of free-floating information.  Every item is associated to at least one context, and some associated to thousands of contexts, just depending on what you need from it.  Each item is universally addressable by it&#8217;s own unique four ordinal vector.  Each item stores its own value, as well as the vectors of each of its associates, grouped by which axis they happen to be associated on.  The items can be associated to other items, or to entire contexts, it&#8217;s completely up to us!  We can associate multiple items on the same axis or split them up, and there is virtually no limit to the number of associates we can have in any particular axis. (Could be anywhere from zero to several million or even sometimes several billion other concepts.)  Since we have this wildy variable method of associating one uniquely addressable item with any number of uniquely addressible items, on any number of axes, it&#8217;s lucky for us that we don&#8217;t need to know how many of what kind of associates we can have right up front.  Even items in the same context can have different numbers of associates, and there is no negative consequence to the other items.  It&#8217;s cool that nobody decided that we&#8217;d have to allocate null associates to represent items without associates, because when we got over a hundred, well that would just be ridiculous!   We certainly can&#8217;t easily convert items into something that fits completely into an Excel spreadsheet!  That&#8217;s quite alright, because we have a lot at our disposal now. (And if we REALLY like Excel spreadsheets, then we can limit the information coming out in such a way that it fits, complete all of the totally unnatural quirkiness of any spreadsheet, some empty columns in some rows, and flat tuples that are all but meaningless without some formal explanation of what they are and what they mean &#8212; like any Excel spreadsheet, pointy haired bosses love those.)</p>
<p>Of course we can predetermine some of the ways in which we&#8217;ll have to establish associations based on the context we wish to use to represent our particular concept, and some of them will be common to all items in the same context.  These we&#8217;ll call &#8216;explicit mappings&#8217; of information.  For example if you&#8217;re adding the concept of an Apple to the Fruit context, you&#8217;ll likely want to also associate it to a member of the Plants context to indicate what it grows on (we can even say that this association exists on the &#8216;Fruit Grows On&#8217; axis.)  These are simple, and the rules are always the same.</p>
<p>We also have the ability to examine concepts we wish to associate with a context AS THEY ARE BEING ADDED TO THE BASE and apply a set of rules to them to determine if, while we&#8217;re at it, we ought to associate them with any other concepts or contexts.  In this way, we can define a list of rules which dynamically determine to which other contexts and concepts we would like to associate with this concept, based on wellâ€¦ what it is.  Contexts and concepts don&#8217;t have a set structure. They can be anything we like them to be, and represent any aspect we&#8217;d like them to.  For example, sure we have a context called Fruit which is associated to all of the things that you and I call &#8220;Fruit&#8221; like Apples, Pears, and Bananas (a personal favorite of mine!) but you can also talk about a context that&#8217;s more abstract like &#8216;Found in Africa&#8217;.  So all of the things we know about that are &#8216;found in Africa&#8217; can be associated to the Found in Africa context.  That means we can have some of the Fruits, and some of the Plants all be associated to the same context of &#8216;Found in Africa&#8217;, so when we ask the Knowledge base for what sort of concepts it knows about in the context of &#8216;found in Africa&#8217; we get both some Fruits and some Plants.  Isn&#8217;t data storage great!?!  </p>
<p>Well, pointy haired bosses are never satisfied, so when they see you can do such wonderful cartwheels with individually simple data, they still want more.  </p>
<p>&#8220;I&#8217;d like to be able to find what sort of Fruits and Plants we can find in Africa that are legal to export to the United States.&#8221;</p>
<p>Just when we thought we&#8217;d thought of everything, we now have to add something else!</p>
<p>&#8220;Ok,&#8221; we tell the boss, &#8220;No Problem!&#8221;  It&#8217;s a good thing that we don&#8217;t have to completely redesign the knowledge base just to add a new context for some concepts we already have!  We can just create a new context called &#8220;Exportable To the US&#8221; and associate the proper concepts with that context as well.  Great!</p>
<p>So, it&#8217;s also relatively simple now to construct &#8216;queries&#8217; for this kind of data store.  When we write the application to show the boss what sorts of Fruits and Plants are Exportable to Africa, then we just have to retrieve all of the items associated with the context of Exportable to the US and also Found in Africa, and then make sure that the results are either Fruits or Plants.  It&#8217;s rather like drawing a venn diagram.  Since we used rules to make the associations on the way into the storage system, we don&#8217;t have to do anything but grab the ready and waiting list of associates we need on the way out!  Sure it takes a tiny bit of effort when the concepts are inserted into the store for the rules to figure out where they are to be associated, but that all runs asynchronously, and we didn&#8217;t care about it when we added it.  Only now when the boss comes to get his answers does the effort really matter!  So, with almost no effort at all, we&#8217;ve given the boss what he wants.  We can only hope that there aren&#8217;t too many more bosses to satisfy today, because we were supposed to go out for a drink after work.  It&#8217;s a good thing everyone uses Associative Knowledgebases, or who knows how long we&#8217;d be here?!?</p>
<p>A Post Facto I forgot to mention, this is a description of a working system. It&#8217;s called Relavance, and it really does all of the wonderful things I just described as if they were hypothetical.</p>
]]></content:encoded>
			<wfw:commentRss>http://davedolan.com/blog/?feed=rss2&amp;p=56</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
