<?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Phil Scott</title><subtitle type="html" /><id>http://blogs.neudesic.com/blogs/phil_scott/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/phil_scott/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.neudesic.com/blogs/phil_scott/atom.aspx" /><generator uri="http://communityserver.org" version="2.0.60217.2664">Community Server</generator><updated>2005-12-05T16:38:00Z</updated><entry><title>Launching the ASP.NET Configuration web site outside of Visual Studio (using Cassini)</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/phil_scott/archive/2006/07/04/187.aspx" /><id>http://blogs.neudesic.com/blogs/phil_scott/archive/2006/07/04/187.aspx</id><published>2006-07-04T01:46:00Z</published><updated>2006-07-04T01:46:00Z</updated><content type="html">&lt;P&gt;Some of you .NET heads out there will probably ask: "So Phil, why would I care to launch the config tool without Visual Studio?&amp;nbsp; I live and breath inside Visual Studio."&amp;nbsp; Well, the answer is, that you might not want to launch it, but your non-programming buddy the System Administrator who has the priviledge and the burden of maintaining user security is &lt;EM&gt;very likely&lt;/EM&gt; to want to do this.&lt;/P&gt;
&lt;P&gt;I'll keep this post short and sweet.&amp;nbsp; Here's an example batch file I wrote (that must be run on the web server hosting the ASP.NET 2.0 application to be configured).&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;@echo off&lt;BR&gt;SET FrameWorkFolder=C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727&lt;BR&gt;SET VFolder=Asp.NetWebAdminFiles&lt;/STRONG&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;BR&gt;&lt;STRONG&gt;SET Port=8099&lt;BR&gt;SET App=/Portal&lt;BR&gt;SET AppPath=C:\Projects\SIS\Portal\&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;explorer "&lt;/STRONG&gt;&lt;/FONT&gt;&lt;A href="http://localhost:%Port%/%VFolder%/default.aspx?applicationPhysicalPath=%AppPath%&amp;amp;applicationUrl=%App%"&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;http://localhost:%Port%/%VFolder%/default.aspx?applicationPhysicalPath=%AppPath%&amp;amp;applicationUrl=%App%&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;"&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&lt;STRONG&gt;%FrameWorkFolder%\WebDev.WebServer.EXE /port:%Port% /path:%FrameWorkFolder%\%VFolder% /vpath:/%VFolder%&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Here are the basic ideas exemplified above:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Be considerate to those (other than you) who will be supporting your ASP.NET 2.0 web site.&amp;nbsp; Give them a way to maintain site security. 
&lt;LI&gt;Since the Cassini web server is built into the .NET 2.0 framework (as WebDev.WebServer.EXE), we can auto-launch any disk folder&amp;nbsp;as a web site. 
&lt;LI&gt;Since the ASP.NET Configuration web site is stored in the C:\Windows\Microsoft.NET\Framework\v*\Asp.NetWebAdminFiles\ folder, we can simply launch a local web site through Cassini to host it for us. 
&lt;LI&gt;The ASP.NET Configuration web site's default web page requires two parameters: 
&lt;OL&gt;
&lt;LI&gt;applicationPhysicalPath (which should point to your ASP.NET 2.0 web site root folder on the hard disk) 
&lt;LI&gt;applicationUrl (which should be your appname as found in your aspnet database's aspnet_applications table)&lt;/LI&gt;&lt;/OL&gt;
&lt;LI&gt;Since the command to launch Cassini is a blocking process, the WebDev.WebServer command must be last in the batch file.&amp;nbsp; This means that we must launch the browser prior to bringing up the Cassini site.&amp;nbsp; It all seems to work out fine for me.&amp;nbsp; Perhaps on other people's machines the timing will not work out so conveniently.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Cheers.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=187" width="1" height="1"&gt;</content><author><name>Phil.Scott</name><uri>http://blogs.neudesic.com/members/Phil.Scott.aspx</uri></author></entry><entry><title>Legacy integration with SQL 2005 CLR Table Value Functions</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/phil_scott/archive/2006/03/10/70.aspx" /><id>http://blogs.neudesic.com/blogs/phil_scott/archive/2006/03/10/70.aspx</id><published>2006-03-10T00:10:00Z</published><updated>2006-03-10T00:10:00Z</updated><content type="html">&lt;P&gt;&lt;FONT size=2&gt;Here's the deal.&amp;nbsp; I'm working on a web project that needs to access legacy data (real time) through a service layer up to a series of web components.&amp;nbsp; The legacy system happens to be an Alpha, running OpenVMS with an old database format called RMS.&amp;nbsp; We have an database driver package for this system (called ConnX), and it runs pretty well.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;The issue is that I'd like to encapsulate the details of the legacy integration from the service layer.&amp;nbsp; You see, the legacy system will be going away sometime in the near future, and over the course of time, we'll be migrating the legacy data onto the MS SQL platform.&amp;nbsp; So, our team decided that we want to minimize the number of components that touch the legacy system, thus minimizing the effort of the future migration.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;We decided (since we're using MS SQL 2005) to see about writing some C# code to run in the SQL CLR engine to perform the job of encapsulating queries to the legacy database.&amp;nbsp; We thought we'd create some .NET 2.0 assemblies, hook them up to SQL 2005 stored procedures and user defined functions, and use them like any other stored SQL code.&amp;nbsp; We've found this to be a very successful strategy.&amp;nbsp; Now, we have user defined &lt;EM&gt;table value functions &lt;/EM&gt;that are encapsulating calls through an OLEDB driver to the legacy database, and the better news is: &lt;STRONG&gt;we can perform SQL JOINs between native MS SQL tables and legacy table data in real time&lt;/STRONG&gt;!!!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;So that's the back story.&amp;nbsp; Here's how to actually do it:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;(In summary, create a .NET Assembly that contains&amp;nbsp;one or more&amp;nbsp;SQLFunction-compatible methods, and then register the assembly and the individual methods with the SQL 2005 server.)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;&lt;FONT size=2&gt;*** Step 1: Create a SQL Database Project ***&lt;/FONT&gt;&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;In Visual Studio 2005, create a new project (Visual C# -&amp;gt; Database -&amp;gt; SQL Server Project).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Choose, or create a database connection reference.&amp;nbsp; (This can be your local development SQL Express server for development purposes.&amp;nbsp; Or, you can point it to your integration or team database.&amp;nbsp; The automatic-deployment feature only seems to work well for me when I point it to my local SQL server on my development PC.)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;In the Solution Explorer, Add a User-Defined Function.&amp;nbsp; (Add -&amp;gt; User-Defined Function) and name the class (I called mine "LegacySQLFunctions.cs", and I renamed my project to "LegacySQLFunctions").&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;It will generate some code like this:&lt;FONT color=#0000ff&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;
&lt;TABLE cellSpacing=0 cellPadding=4&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff size=1&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt; System;&lt;BR&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt; System.Data;&lt;BR&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt; System.Data.SqlClient;&lt;BR&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt; System.Data.SqlTypes;&lt;BR&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New" size=1&gt; Microsoft.SqlServer.Server;&lt;BR&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;partial&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;class&lt;/FONT&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=1&gt;LegacySQLFunctions&lt;BR&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;[Microsoft.SqlServer.Server.&lt;FONT color=#008080&gt;SqlFunction&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;]&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;static&lt;/FONT&gt; &lt;FONT color=#008080&gt;SqlString&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt; LegacySQLFunctions()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Put your code here&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#008080&gt;SqlString&lt;/FONT&gt;(&lt;FONT color=#800000&gt;"Hello"&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt;);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;};&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;*** Step 2: Program the C# method for the SQL Table Valued Function***&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;I think of this kind of like the ASP.NET concept of a code-behind module.&amp;nbsp; This assembly is the .NET&amp;nbsp;&lt;EM&gt;code behind&lt;/EM&gt; for the SQL function I need.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;To create a SQL Function that returns table values rather than scalar values, you have to do a few extra things:&lt;/FONT&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT size=2&gt;Edit the method attributes to specify the DataAccess, TableDefinition, and FillRowMethodName.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Change the method to return an IEnumerable type.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Write a separate method to parse the individual IEnumerable members into the defined output table columns.&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;FONT size=2&gt;The idea behind the IEnumerable return type and the FillRowMethodName attribute is that the SQL CLR engine is going to call the main method for the SQL Function, expect to receive an enumerable object, will then walk the enumeration calling the method specified in the FillRowMethodName attribute to parse each record into the expected columns specified for output.&amp;nbsp; Here's how mine is structured:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;
&lt;TABLE cellSpacing=0 cellPadding=4&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;FONT&gt;&lt;FONT color=#0000ff&gt;
&lt;P&gt;&lt;FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=1&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt; System;&lt;BR&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt; System.Data;&lt;BR&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt; System.Data.SqlClient;&lt;BR&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt; System.Data.SqlTypes;&lt;BR&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT&gt; Microsoft.SqlServer.Server;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt; System.Collections;&lt;BR&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt; System.Data.OleDb;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT color=#0000ff&gt;&lt;BR&gt;&lt;FONT face="Courier New" size=1&gt;namespace&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt; ACME.TheApp.MyPortal&lt;BR&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;BR&gt;&lt;FONT face="Courier New" size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt; &lt;FONT color=#0000ff&gt;partial&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;class&lt;/FONT&gt; &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=1&gt;LegacySQLFunctions&lt;BR&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New" size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#008000&gt;//--- Define a main entry point for a SQL 2005 User-Defined-Function that returns a TABLE value type ---&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[&lt;/FONT&gt;&lt;FONT color=#008080&gt;SqlFunction&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#0000ff&gt;(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT color=#000000&gt;FillRowMethodName =&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#800000&gt;"ParseUserDetailRow"&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#0000ff&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#000000&gt;TableDefinition =&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#800000&gt;"UserAccount NVARCHAR(10), FirstName NVARCHAR(14),&amp;nbsp;LastName NVARCHAR(14), DateOfBirth DATETIME"&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#0000ff&gt;,&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#000000&gt;DataAccess&lt;/FONT&gt;&lt;FONT color=#000000&gt; =&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#008080&gt;DataAccessKind&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=1&gt;.Read&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)]&lt;/FONT&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;static&lt;/FONT&gt;&amp;nbsp;&lt;FONT color=#008080&gt;IEnumerable&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt; &lt;FONT color=#000000&gt;GetUserDetails&lt;/FONT&gt;( string &lt;FONT color=#000000&gt;userAccountLike&lt;/FONT&gt; )&lt;BR&gt;&amp;nbsp;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;/FONT&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New" color=#008000 size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Put your legacy integration code here.&amp;nbsp; It should query your legacy database and construct any sort&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New" color=#008000 size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// of IEnumerable object for&amp;nbsp;return.&amp;nbsp; In my case, I used the Rows property of DataTable as the return value.&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT&gt;&lt;FONT face="Courier New" color=#008000 size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// By the way, the legacy connection string, legacy user and legacy password should be saved&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT face="Courier New" color=#008000 size=1&gt;in a configuration table somewhere else on the SQL server, retrieved and cached.&amp;nbsp;&amp;nbsp; But for simplicity of&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// &lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT&gt;&lt;FONT face="Courier New" color=#008000 size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;&lt;FONT color=#000000&gt; legacyUser =&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt; &lt;FONT color=#800000&gt;"imNotTellingYou"&lt;/FONT&gt;&lt;/FONT&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;&lt;FONT color=#000000&gt; legacyPwd =&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt; &lt;FONT color=#800000&gt;"StillNotDumbEnoughToShowThisInABlog"&lt;/FONT&gt;&lt;/FONT&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT color=#008000&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&lt;/FONT&gt; &lt;FONT color=#000000&gt;legacyConnectString&lt;/FONT&gt; = &lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;.Format(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT color=#008000&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#800000&gt;@"provider=connx ole db provider; Data Source=C:\Connx32\UTILS\legacy.CDD;User ID={0};Password={1};"&lt;/FONT&gt;,&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT color=#008000&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt;legacyUser, legacyPwd&lt;/FONT&gt;);&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&lt;/FONT&gt; &lt;FONT color=#000000&gt;queryString&lt;/FONT&gt; = &lt;FONT color=#800000&gt;"SELECT USRACCT,&amp;nbsp;FNAME, LNAME, DOB&lt;/FONT&gt;&lt;FONT color=#800000&gt;&amp;nbsp;"&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;+ &lt;FONT color=#800000&gt;"FROM&amp;nbsp;SYSUSR "&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt;+ &lt;FONT color=#800000&gt;"WHERE USRACCT LIKE '"&lt;/FONT&gt; + &lt;FONT color=#000000&gt;userAccountLike&lt;/FONT&gt; + &lt;FONT color=#800000&gt;"'"&lt;/FONT&gt;;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;using&lt;/FONT&gt; (&lt;FONT color=#008080&gt;OleDbConnection&lt;/FONT&gt; &lt;FONT color=#000000&gt;connection&lt;/FONT&gt; = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#008080&gt;OleDbConnection&lt;/FONT&gt;(&lt;FONT color=#000000&gt;legacyConnectString&lt;/FONT&gt;))&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;using&lt;/FONT&gt; (&lt;FONT color=#008080&gt;OleDbCommand&lt;/FONT&gt; &lt;FONT color=#000000&gt;cmd&lt;/FONT&gt; = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#008080&gt;OleDbCommand&lt;/FONT&gt;(&lt;FONT color=#000000&gt;queryString&lt;/FONT&gt;, &lt;FONT color=#000000&gt;connection&lt;/FONT&gt;))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt; (&lt;FONT color=#008080&gt;OleDbDataAdapter&lt;/FONT&gt; &lt;FONT color=#000000&gt;da&lt;/FONT&gt; = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#008080&gt;OleDbDataAdapter&lt;/FONT&gt;(&lt;FONT color=#000000&gt;cmd&lt;/FONT&gt;))&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt;&lt;FONT color=#000000&gt;{&lt;/FONT&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#008080&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DataTable&lt;/FONT&gt;&lt;FONT color=#000000&gt; dt =&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#008080&gt;DataTable&lt;/FONT&gt;();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt;&lt;FONT color=#000000&gt;da.Fill(dt);&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#0000ff&gt;return&lt;/FONT&gt; &lt;FONT color=#000000&gt;dt.Rows&lt;/FONT&gt;;&amp;nbsp;&amp;nbsp;&amp;nbsp;// the Rows collection&amp;nbsp;implements IEnumerable, so I am safe to return this to SQL.&lt;BR&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#000000 size=1&gt;}&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#000000 size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT&gt;&lt;FONT face="Courier New" size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#008000&gt;//--- Define the&amp;nbsp;call-back function that will parse each row in the enumeration ---&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public static void &lt;FONT color=#000000&gt;ParseUserDetailRow&lt;/FONT&gt;( object&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#000000&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;item, &lt;FONT color=#0000ff&gt;out&amp;nbsp;string&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#000000&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;userAccount,&amp;nbsp;&lt;FONT color=#0000ff&gt;out string&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#000000 size=1&gt;firstName,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT color=#000000&gt;&lt;FONT color=#000000&gt;&lt;FONT color=#000000&gt;&lt;FONT face="Courier New" color=#0000ff size=1&gt;out string&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#000000&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;lastName,&amp;nbsp;&lt;FONT color=#0000ff&gt;out&lt;/FONT&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#008080&gt;DateTime&lt;/FONT&gt;&lt;FONT color=#000000&gt;&amp;nbsp;dateOfBirth&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#000000&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#008080&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt;{&lt;/FONT&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;FONT color=#000000&gt;&lt;FONT color=#000000&gt;&lt;FONT color=#000000&gt;&lt;FONT color=#000000&gt;&lt;FONT color=#000000&gt;&lt;FONT color=#0000ff&gt;&lt;FONT color=#008080&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#008080&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DataRow&lt;/FONT&gt; &lt;FONT color=#000000&gt;row = (&lt;/FONT&gt;&lt;FONT color=#008080&gt;DataRow&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt;)item;&lt;BR&gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#000000&gt;userAccount = row[&lt;/FONT&gt;&lt;FONT color=#800000&gt;"USRACCT"&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt;].ToString();&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#000000&gt;firstName = row[&lt;/FONT&gt;&lt;FONT color=#800000&gt;"FNAME"&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt;].ToString();&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#000000&gt;lastName = row[&lt;/FONT&gt;&lt;FONT color=#800000&gt;"LNAME"&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt;].ToString();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dateOfBirth =&lt;/FONT&gt; &lt;FONT color=#008080&gt;Convert&lt;/FONT&gt;&lt;FONT color=#000000&gt;.ToDateTime( row[&lt;/FONT&gt;&lt;FONT color=#800000&gt;"DOB"&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#000000 size=1&gt;]);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT&gt;&lt;BR&gt;&lt;FONT face="Courier New" size=1&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;BR&gt;}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr&gt;&lt;FONT&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;U&gt;*** Step 3: Register the assembly and function with SQL ***&lt;/U&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Now, I copy the DLL I've built over to my SQL 2005 server.&amp;nbsp; (In my case, I created a folder on my SQL server named C:\Components\SQLCLR\ into which my .NET assemblies go.)&amp;nbsp; I copy the bin\Debug\LegacySQLFunctions.dll file to the server in C:\Components\SQLCLR\.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Next, I open up SQL 2005 Server Management Studio, connect to the database I'm going to keep the Legacy functions in, and open a new query window.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;I write and execute the following T-SQL commands:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;
&lt;TABLE cellSpacing=0 cellPadding=4&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;FONT color=#0000ff size=2&gt;
&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT face="Courier New" size=1&gt;IF&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#808080&gt;EXISTS&lt;/FONT&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#808080&gt;(&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;SELECT&lt;/FONT&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#808080&gt;*&lt;/FONT&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;FROM&lt;/FONT&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#008000&gt;sys.assemblies&lt;/FONT&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;WHERE&lt;/FONT&gt;&lt;FONT color=#000000&gt; [name] &lt;/FONT&gt;&lt;FONT color=#808080&gt;=&lt;/FONT&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000&gt;'LegacySQLFunctions'&lt;/FONT&gt;&lt;FONT color=#808080&gt;)&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;DROP&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;ASSEMBLY&lt;/FONT&gt;&lt;FONT color=#000000&gt; LegacySQLFunctions&lt;/FONT&gt;&lt;FONT color=#808080&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt;GO&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#008000&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=1&gt;-- If you're going to use CLR code that connects to unmanaged code (e.g. C++ OLEDB drivers)&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt;-- you'll need to enable TRUSTWORTHY attribute on the database, and use the UNSAFE&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt;-- permission set on the assembly.&amp;nbsp; Otherwise, skip this command, and use PERMISSION_SET=Safe&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;ALTER&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;DATABASE&lt;/FONT&gt;&lt;FONT color=#000000&gt; MyPortal &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;SET&lt;/FONT&gt;&lt;FONT color=#000000&gt; TRUSTWORTHY &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;ON&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt;GO&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=1&gt;
&lt;P&gt;-- Add the assembly and CLR integration based stored procedure&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;CREATE&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;ASSEMBLY&lt;/FONT&gt;&lt;FONT color=#000000&gt; LegacySQLFunctions&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;FROM&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000&gt;'C:\components\SQLCLR\LegacySQLFunctions.dll'&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;WITH&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt; PERMISSION_SET &lt;/FONT&gt;&lt;FONT color=#808080&gt;=&lt;/FONT&gt;&lt;FONT color=#000000&gt; UnSafe&lt;/FONT&gt;&lt;FONT color=#808080&gt;;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt;GO&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=1&gt;
&lt;P&gt;-- Now, bind the SQL function to the code-behind method in the assembly&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;CREATE&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;FUNCTION&lt;/FONT&gt;&lt;FONT color=#000000&gt; dbo&lt;/FONT&gt;&lt;FONT color=#808080&gt;.&lt;/FONT&gt;&lt;FONT color=#000000&gt;fnGetUserDetails&lt;/FONT&gt;&lt;FONT color=#808080&gt;(&lt;/FONT&gt;&lt;FONT color=#000000&gt; @UserAccountLike &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;NVARCHAR&lt;/FONT&gt;&lt;FONT color=#808080&gt;(&lt;/FONT&gt;&lt;FONT color=#000000&gt;20&lt;/FONT&gt;&lt;FONT color=#808080&gt;)&lt;/FONT&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#808080&gt;)&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;RETURNS&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;TABLE&lt;/FONT&gt;&lt;FONT color=#000000&gt; &lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#808080 size=1&gt;(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT size=1&gt;&lt;FONT face="Courier New"&gt;UserAccount &lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;NVARCHAR&lt;/FONT&gt;&lt;FONT color=#808080&gt;(&lt;/FONT&gt;10&lt;FONT color=#808080&gt;),&lt;/FONT&gt; FirstName &lt;FONT color=#0000ff&gt;NVARCHAR&lt;/FONT&gt;&lt;FONT color=#808080&gt;(&lt;/FONT&gt;14&lt;FONT color=#808080&gt;),&lt;/FONT&gt; LastName &lt;FONT color=#0000ff&gt;NVARCHAR&lt;/FONT&gt;&lt;FONT color=#808080&gt;(&lt;/FONT&gt;14&lt;FONT color=#808080&gt;),&lt;/FONT&gt; DateOfBirth &lt;FONT color=#0000ff&gt;DATETIME&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#808080 size=1&gt;)&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;AS&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=1&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;EXTERNAL&lt;/FONT&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;NAME&lt;/FONT&gt;&lt;FONT color=#000000&gt; LegacySQLFunctions&lt;/FONT&gt;&lt;FONT color=#808080&gt;.&lt;/FONT&gt;&lt;FONT color=#000000&gt;[ACME.TheApp.MyPortal.LegacySQLFunctions]&lt;/FONT&gt;&lt;FONT color=#808080&gt;.&lt;/FONT&gt;&lt;FONT color=#000000&gt;GetUserDetails&lt;/FONT&gt;&lt;FONT color=#808080&gt;;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;After running the above SQL query, the function should be callable from anywhere within SQL code.&amp;nbsp; Here are a few fictitious examples of how I can use this function now that it's been created:&lt;/P&gt;
&lt;P&gt;
&lt;TABLE cellSpacing=0 cellPadding=4&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;FONT&gt;&lt;FONT face="Courier New" color=#008000 size=1&gt;
&lt;P&gt;-- Example 1: returns all user detail records from the legacy database where the legacy&lt;BR&gt;-- user account name begins with JWHITE&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;SELECT&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;&lt;FONT face="Courier New"&gt; &lt;FONT color=#808080&gt;*&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;FROM&lt;/FONT&gt; dbo&lt;FONT color=#808080&gt;.&lt;/FONT&gt;fnGetUserDetails&lt;FONT color=#808080&gt;(&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;'JWHITE%'&lt;/FONT&gt; &lt;FONT color=#808080&gt;)&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=1&gt;
&lt;P&gt;-- Example 2: Retrieves recently logged in Portal users, with a join to legacy user details.&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;SELECT&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt; PortalUser&lt;FONT color=#808080&gt;.&lt;/FONT&gt;LastLoginDate&lt;FONT color=#808080&gt;,&lt;/FONT&gt; ud&lt;FONT color=#808080&gt;.&lt;/FONT&gt;FirstName&lt;FONT color=#808080&gt;,&lt;/FONT&gt; ud&lt;FONT color=#808080&gt;.&lt;/FONT&gt;LastName&lt;FONT color=#808080&gt;,&lt;/FONT&gt; ud&lt;FONT color=#808080&gt;.&lt;/FONT&gt;DateOfBirth&lt;FONT color=#808080&gt;,&lt;/FONT&gt; PortalUser&lt;FONT color=#808080&gt;.&lt;/FONT&gt;Email&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;FROM&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=1&gt; PortalUser&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#808080&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;INNER&lt;/FONT&gt; &lt;FONT color=#808080&gt;JOIN&lt;/FONT&gt; dbo&lt;FONT color=#808080&gt;.&lt;/FONT&gt;fnGetUserDetails&lt;FONT color=#808080&gt;(&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;'%'&lt;/FONT&gt; &lt;FONT color=#808080&gt;)&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;AS&lt;/FONT&gt; ud&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ON&lt;/FONT&gt; PortalUser&lt;FONT color=#808080&gt;.&lt;/FONT&gt;LegacyAccountName &lt;FONT color=#808080&gt;=&lt;/FONT&gt; ud&lt;FONT color=#808080&gt;.&lt;/FONT&gt;UserAccount&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New" size=1&gt;WHERE&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;&lt;FONT face="Courier New"&gt; PortalUser&lt;FONT color=#808080&gt;.&lt;/FONT&gt;LastLoginDate &lt;FONT color=#808080&gt;&amp;gt;&lt;/FONT&gt; &lt;FONT color=#ff00ff&gt;DateAdd&lt;/FONT&gt;&lt;FONT color=#808080&gt;(&lt;/FONT&gt;dd&lt;FONT color=#808080&gt;,&lt;/FONT&gt; &lt;FONT color=#808080&gt;-&lt;/FONT&gt;1&lt;FONT color=#808080&gt;,&lt;/FONT&gt; &lt;FONT color=#ff00ff&gt;getdate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#808080&gt;&lt;FONT face="Courier New"&gt;())&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&lt;FONT face="Courier New"&gt;ORDER&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#000000&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff&gt;BY&lt;/FONT&gt;&lt;FONT color=#000000&gt; PortalUser&lt;/FONT&gt;&lt;FONT color=#808080&gt;.&lt;/FONT&gt;&lt;FONT color=#000000&gt;LastLoginDate &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT face="Courier New" size=1&gt;DESC&lt;/FONT&gt;&lt;/FONT&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;The CLR assembly runs very fast.&amp;nbsp; The above code runs sub-second.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Conclusion&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;SQL 2005 User Defined Functions coupled with the .NET CLR is&amp;nbsp;a beautiful thing!!!&amp;nbsp; Certainly great for legacy integration and encapsulation.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=70" width="1" height="1"&gt;</content><author><name>Phil.Scott</name><uri>http://blogs.neudesic.com/members/Phil.Scott.aspx</uri></author></entry><entry><title>Waterfall is back with a vengeance!</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/phil_scott/archive/2006/03/10/68.aspx" /><id>http://blogs.neudesic.com/blogs/phil_scott/archive/2006/03/10/68.aspx</id><published>2006-03-10T00:08:00Z</published><updated>2006-03-10T00:08:00Z</updated><content type="html">&lt;P&gt;Ok.&amp;nbsp; Short post.&amp;nbsp; But it's worth it.&amp;nbsp; Take a look at &lt;A href="http://www.waterfall2006.com/"&gt;http://www.waterfall2006.com/&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;I'm rolling on the floor laughing!&amp;nbsp; Thanks Curt for the link!&lt;/P&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=68" width="1" height="1"&gt;</content><author><name>Phil.Scott</name><uri>http://blogs.neudesic.com/members/Phil.Scott.aspx</uri></author></entry><entry><title>MSF Agile - what's it all mean?</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/phil_scott/archive/2005/12/16/14.aspx" /><id>http://blogs.neudesic.com/blogs/phil_scott/archive/2005/12/16/14.aspx</id><published>2005-12-16T22:48:00Z</published><updated>2005-12-16T22:48:00Z</updated><content type="html">&lt;P&gt;With the looming public release of Microsoft Visual Studio 2005 Team System, we are all hearing about "MSF Agile".&amp;nbsp;&amp;nbsp;Do we know what MSF Agile means to our projects?&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Some of us in the software development industry already know what &lt;A href="http://en.wikipedia.org/wiki/Agile_software_development"&gt;Agile Software Development&lt;/A&gt;&amp;nbsp;is, while others have been so focussed on the &lt;A href="http://www.pmi.org/"&gt;PMI&lt;/A&gt; groundswell that the word "agile" never reached their ears.&lt;/P&gt;
&lt;P&gt;What frightens me is that MSF Agile is likely to be the first introduction to Agile Software Development for many software developers and project managers in 2006 and 2007.&amp;nbsp; Why is that a problem?&amp;nbsp; Is there something wrong with MSF Agile?&amp;nbsp; The issue is that, like MSF, MSF Agile is not a prescriptive methodology.&amp;nbsp; It never claimed to be.&amp;nbsp; It is a framework, with which one may develop or compare&amp;nbsp;methodologies; and it contains many excellent resources to help practitioners study patterns and practices in software development.&amp;nbsp; It is akin to a set of principals and ideas without a detailed application guide or set of practical examples.&amp;nbsp; As such, developers and project managers who might not be otherwise educated about Agile Software Development methodologies and practices are likely to be lulled into a belief that by using Visual Studio 2005 Team System, they are practicing Agile Software Development!&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Don't get me wrong.&amp;nbsp; I believe that MSF Agile will be a beneficial guideline for certain audiences.&amp;nbsp; I just don't think that the average guy on the street, writing C# 2.0 code or crafting a project gantt chart is going to benefit directly from studying MSF Agile.&amp;nbsp; These folks (in my humble opinion) might be better served to enter the agile community with something like SCRUM or Crystal Clear.&amp;nbsp; Once they've applied the specific practices to live projects, then MSF Agile might hold more meaning to them.&lt;/P&gt;
&lt;P&gt;What I'd&amp;nbsp;like to see out of Team System is a set of process guidance templates for each of the major Agile Software Development practices.&amp;nbsp; While I don't think it would be appropriate for Microsoft to take on this responsibility, I would hope to see more TFS templates coming out of the agile community for SCRUM, XP, Crystal Clear, Lean and the like.&amp;nbsp; I definitely like what Howard van Rooijen is doing with &lt;A href="http://blogs.conchango.com/howardvanrooijen/archive/2005/10/27/2311.aspx"&gt;SCRUM work items for TFS&lt;/A&gt;.&amp;nbsp; If TFS had a gallery of these templates from the agile community (perhaps through MSDN), then developers and PMs using TFS would have more visibility into the fact that there really are well defined methodologies for Agile Software Development.&lt;/P&gt;
&lt;P&gt;All of that said, I love what I see coming out of Visual Studio Team System as it relates to Agile Software Development.&amp;nbsp; Microsoft has incorporated many tools, reports and views that will make feature driven development practitioners and Scrum Masters very happy.&amp;nbsp; Work item backlog integrated with change history, defect and velocity reports, unplanned work analysis... all of these things should get project&amp;nbsp;leaders in the agile community very excited.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Suggestions for the uninitiated:&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Read the very succinct wiki on&amp;nbsp;&lt;A href="http://en.wikipedia.org/wiki/Agile_software_development"&gt;Agile Software Development&lt;/A&gt; 
&lt;LI&gt;Listen to the &lt;A href="http://agiletoolkit.libsyn.com/"&gt;Agile Toolkit Podcast&lt;/A&gt; (many of the Agile Manifesto&amp;nbsp;signatories are interviewed here) 
&lt;LI&gt;Pick one of the Agile methodologies to study, buy a book, read articles on-line about it.&amp;nbsp;&lt;BR&gt;(Extreme Programming, Scrum, Adapdive Software Development, Crystal Clear, DSDM, Feature Driven Development, Lean Software Development) 
&lt;LI&gt;If you're still interested, then get into a project with an experienced Agile Software Development practitioner or team.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Interesting links related to Agile Software Development and MSF Agile:&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Agile Manifesto (the unifying beliefs)&lt;BR&gt;&lt;A href="http://www.agilemanifesto.org/"&gt;http://www.agilemanifesto.org/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Short introduction to Agile Software Development&lt;BR&gt;&lt;A href="http://www.agilealliance.com/intro"&gt;http://www.agilealliance.com/intro&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;MSF for Agile Software Devleopment&lt;BR&gt;&lt;A href="http://msdn.microsoft.com/vstudio/teamsystem/msf/msfagile/default.aspx"&gt;http://msdn.microsoft.com/vstudio/teamsystem/msf/msfagile/default.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;An early blog by Scott Bellware, somewhat critical of&amp;nbsp;MSF Agile&lt;BR&gt;&lt;A href="http://geekswithblogs.net/sbellware/archive/2005/02/03/21964.aspx"&gt;http://geekswithblogs.net/sbellware/archive/2005/02/03/21964.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Microsoft VSTS&lt;BR&gt;&lt;A href="http://lab.msdn.microsoft.com/teamsystem/"&gt;http://lab.msdn.microsoft.com/teamsystem/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Microsoft's David Anderson gives a&amp;nbsp;webcast about Lean Thinking in MSF v4.0&lt;BR&gt;&lt;A href="http://haloscan.com/tb/agileman/Lean_Thinking_in_MSF_v4_0_Webcast"&gt;http://haloscan.com/tb/agileman/Lean_Thinking_in_MSF_v4_0_Webcast&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;/EM&gt;&lt;BR&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=14" width="1" height="1"&gt;</content><author><name>Phil.Scott</name><uri>http://blogs.neudesic.com/members/Phil.Scott.aspx</uri></author></entry><entry><title>SQL Query Performance - Do you feel dirty?  (Dirty Reads)</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/phil_scott/archive/2005/12/05/11.aspx" /><id>http://blogs.neudesic.com/blogs/phil_scott/archive/2005/12/05/11.aspx</id><published>2005-12-05T16:38:00Z</published><updated>2005-12-05T16:38:00Z</updated><content type="html">&lt;P&gt;Ok, so I'm feeling guilty that I was in such a rush to get my blog, and then I failed to posting anything for almost a week.&amp;nbsp; Well, I thought that rather than let another week go by I ought to post something of use.&amp;nbsp; But what to post?&amp;nbsp; It just so happens that I have been working on a document to share some of my experience with optimizing TSQL queries (MS SQL 2000 that is).&amp;nbsp; I know that in the spirit of SQL 2005, it may seem blasphemy to share knowledge about something that was so yesterday as SQL 2000.&amp;nbsp; But, that's what I have.&amp;nbsp; And there you are.&lt;/P&gt;
&lt;P&gt;Today's installment will be a tidbit about optimizing queries specifically using locking hints.&amp;nbsp; Depending on the shape and use of the database, I have used this technique to reduce 30-second queries to 2 seconds.&amp;nbsp; Other times, it has made no noticable difference at all.&amp;nbsp; It all depends on the kind of volume and types of transactions hitting the tables being queried.&lt;/P&gt;
&lt;P&gt;I'll follow this post up later with more of the same subject.&amp;nbsp; Here you go:&lt;/P&gt;
&lt;P&gt;---------------------------------------------------------------------------------------------------&lt;/P&gt;
&lt;H1&gt;&lt;A name=_Toc113191505&gt;&lt;FONT face=Arial size=5&gt;Turn off record locking in SELECT&lt;/FONT&gt;&lt;/A&gt;&lt;/H1&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Microsoft SQL has several levels of lock granularity.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The server does its best to “pessimistically” control concurrency with locks.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;This means that the server assumes the worst when it comes to possible concurrency collisions, and protects you from yourself.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;I&gt;Locks can be acquired on rows, pages, keys, ranges of keys, indexes, tables, or databases.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;SQL Server dynamically determines the appropriate level at which to place locks for each Transact-SQL statement.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The level at which locks are acquired can vary for different objects referenced by the same query; for example one table may be very small and have a table lock applied, while another, larger table may have row locks applied. The level at which locks are applied does not have to be specified by users and needs no configuration by administrators. Each instance of SQL Server ensures that locks granted at one level of granularity respect locks granted at another level. [SQL 2000 online help]&lt;/I&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;While the server assumes the worst when trying to protect us from ourselves, it also delivers less performance while doing so, and in some circumstances may have dire performance consequences.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;B&gt;Remember Optimization Axiom #2&lt;/B&gt;: “Locking is &lt;U&gt;not&lt;/U&gt; your friend.”&amp;nbsp; (when optimizing queries)&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;B&gt;Example 1:&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Imagine that your program runs the following summary query to display revenue for 2005:&lt;/P&gt;
&lt;DIV&gt;
&lt;P class=CodeExample&gt;&lt;FONT face="Courier New" size=2&gt;SELECT DivCode, DeptCode, SUM(Revenue) AS RevenueSubTotal &lt;BR&gt;FROM AccountsJournal&lt;BR&gt;WHERE ClosedDate BETWEEN ‘2005-01-01’ AND ‘2006-01-01’&lt;BR&gt;GROUP BY DivCode, DeptCode&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P class=MsoNormal&gt;Let’s say that this AccountsJournal table contains 1,500,000 rows of data, and already has an index for DivCode+DeptCode as well as a separate index for ClosedDate.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Any problems with this?&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Indexes are in order.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The query is optimized.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;But there is a problem.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;A big one.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;This had better not be running on the main production database during business hours.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;It &lt;I&gt;might&lt;/I&gt; run in less than 3 minutes, but during that time, the SQL server’s locking traffic cop is deciding the fate of every production user of the AccountsJournal table, and whether or not they’ll be allowed to post their updates in a timely manner.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Almost as bad, is the fact that this query will also be forced to wait while other update queries finish running.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Do you feel lucky?&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;H2&gt;&lt;A name=_Toc113191506&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;What is a dirty read?&lt;/FONT&gt;&lt;/EM&gt;&lt;/A&gt;&lt;/H2&gt;
&lt;P class=MsoNormal&gt;Simply put, a dirty read is where a query reads data from the database without lock protection.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Without lock protection, you cannot be guaranteed that the data isn’t changing during the time that the query is running.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;SQL Server assumes that you need to be protected from concurrency issues even when you’re running a SELECT statement.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;What you need to decide is whether or not you agree with it’s assessment of the danger.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Ask yourself these questions:&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI class=MsoNormal&gt;While my SELECT query is running, does it matter whether or not someone else makes a change to a record or two?&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Will it affect my outcome in a meaningful way? 
&lt;LI class=MsoNormal&gt;Are any of the tables in my query in danger of being affected by a mass-update while the query is in the process of running?&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;If so, would it be bad if my query only saw part of the mass-update?&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;If the answer is, “No, my query doesn’t mind,” then you need to turn off the locking for your query.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;This is called a “dirty read”.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;You’re willing to accept less than a pristine and untouched snapshot of data.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;H2&gt;&lt;A name=_Toc113191507&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;When should a dirty read be used?&lt;/FONT&gt;&lt;/EM&gt;&lt;/A&gt;&lt;/H2&gt;
&lt;P class=MsoNormal&gt;A better question is, “when shouldn’t a dirty read be used?”&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;It is the author’s opinion and experience that the best practice for database developers is to use dirty reads as the rule, rather than the exception.&amp;nbsp;&lt;SPAN&gt;&amp;nbsp;Let the hate mail begin...&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;In fact, at two telecommunications companies in the author’s past, it was a serious offense for developers to write any query without enabling dirty reads (without strong justification).&lt;SPAN&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;At In Touch Communications, in 2001, the development staff had no SQL standards.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The MS SQL 2000 database that powered their Siebel CRM system was deadlocking often, and the Customer Service and Sales departments would crash in Siebel at least twice per week.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;In 90% of the cases, the issue turned out to be long-running queries that had been hand written by developers for various purposes.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Some were queries for reports.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Others were custom scheduled SQL jobs.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;All of them used the default locking of SQL server.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Once the In Touch Communications I.T. staff migrated all appropriate stored procedures (99%) to use dirty-reads, the deadlocks went away.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;Siebel stopped crashing.&amp;nbsp; Later, I.T. afforded a separate SQL server to run their reports, which further increased system performance (also a best practice).&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;It is rare that a SELECT statement is negatively impacted by using a dirty read.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;The only cases the author has run into have been in stored procedures that run one or more SELECT statements to gather information just prior to a mass update or delete.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;In these rare cases, a qualified DBA should consider the data dependencies, and decide whether or not dirty reads are safe for that stored procedure. &lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;If locking is allowed on a long-running query (15+ seconds), then the DBA must consider how this query will affect the rest of the system.&lt;/P&gt;
&lt;H2&gt;&lt;A name=_Toc113191508&gt;&lt;EM&gt;&lt;FONT face=Arial&gt;How to use dirty reads&lt;/FONT&gt;&lt;/EM&gt;&lt;/A&gt;&lt;/H2&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Best practice rules:&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI class=MsoNormal&gt;All SELECT queries should use the &lt;B&gt;WITH (NOLOCK)&lt;/B&gt; directive for every table involved in the query. 
&lt;LI class=MsoNormal&gt;If it is not practical to use the WITH (NOLOCK) directive on every query, then upon opening a database connection, enable dirty reads as the default behavior for the entire database connection using:&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;B&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED&lt;/B&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;B&gt;Example 2:&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;To change our previous revenue query to use dirty reads:&lt;/P&gt;
&lt;DIV&gt;
&lt;P class=CodeExample&gt;&lt;FONT face="Courier New" size=2&gt;SELECT DivCode, DeptCode, SUM(Revenue) AS RevenueSubTotal &lt;BR&gt;FROM AccountsJournal &lt;SPAN&gt;&lt;U&gt;WITH (NOLOCK)&lt;/U&gt;&lt;/SPAN&gt;&lt;BR&gt;WHERE ClosedDate BETWEEN ‘2005-01-01’ AND ‘2006-01-01’&lt;BR&gt;GROUP BY DivCode, DeptCode&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;B&gt;Example 3:&lt;o:p&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Here’s an example of WITH (NOLOCK) on a more complex query:&lt;/P&gt;
&lt;P class=MsoNormal&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/P&gt;
&lt;DIV&gt;
&lt;P class=CodeExample&gt;&lt;FONT face="Courier New" size=2&gt;SELECT DISTINCT &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;P.Handle, SM.SeatDescription&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;, PS.PreFlopSeen, PS.FlopSeen&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;, PP.Invested, PP.Won, PP.MonetaryProfit&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=CodeExample&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;FROM tblPlayer P &lt;SPAN&gt;&lt;U&gt;WITH (NOLOCK)&lt;/U&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=CodeExample&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;INNER JOIN tblPlayerStats PS &lt;SPAN&gt;&lt;U&gt;WITH (NOLOCK)&lt;/U&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ON P.PlayerID = PS.PlayerID&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=CodeExample&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;INNER JOIN tblPlayerHand PH &lt;SPAN&gt;&lt;U&gt;WITH (NOLOCK)&lt;/U&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ON P.PlayerID = PH.PlayerID&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=CodeExample&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;INNER JOIN &lt;SPAN&gt;&lt;U&gt;dbo.tfn_Hand_PlayerCount()&lt;/U&gt;&lt;/SPAN&gt; HPC&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ON PH.HandID = HPC.HandID&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=CodeExample&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;LEFT JOIN (&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=CodeExample&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;SELECT SM.PlayerCount, SM.SeatIndex&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;, SM.SeatID, ST.SeatDescription&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;FROM tblSeatMap SM &lt;SPAN&gt;&lt;U&gt;WITH (NOLOCK)&lt;/U&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;INNER JOIN tblSeat ST &lt;SPAN&gt;&lt;U&gt;WITH (NOLOCK)&lt;/U&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ON SM.SeatID = ST.SeatID&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WHERE ST.StreetID = 2&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=CodeExample&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;) SM&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ON SM.PlayerCount = HPC.PlayerCount &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;AND SM.SeatIndex = PH.PreFlopSeatIndex&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=CodeExample&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;LEFT JOIN &lt;SPAN&gt;&lt;U&gt;dbo.tfn_PlayerProfit_Summary()&lt;/U&gt;&lt;/SPAN&gt; PP&lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ON P.PlayerID = PP.PlayerID&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=CodeExample&gt;&lt;FONT face="Courier New" size=2&gt;WHERE NOT SM.SeatID IS NULL&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P class=MsoNormal&gt;Notice that both User Defined Functions in Example 3 do not have a WITH(NOLOCK) directive.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;More on that later.&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal&gt;Until next time...&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Phil Scott&lt;BR&gt;&lt;A href="http://www.neudesic.com"&gt;www.neudesic.com&lt;/A&gt;&lt;BR&gt;&lt;A href="mailto:phil.scott@neudesic.com"&gt;phil.scott@neudesic.com&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=11" width="1" height="1"&gt;</content><author><name>Phil.Scott</name><uri>http://blogs.neudesic.com/members/Phil.Scott.aspx</uri></author></entry></feed>