I got the geo-location to work in SQLCLR! It's hard to decide what to post as code on a blog like this, but this little 'component' would work as a standalone unit for any website with a SQL Server 2005 back end that has a use for country/city/state and latitude/longitude for IP addresses (the location of the ISP is probably more accurate, but that's close enough for most people - any closer, and you probably have privacy issues!). The process of creating and deploying a .NET DLL in the Express editions was tougher than the code itself - but not hard to do once I dug up some documentation and samples (referenced below). Basically, an SQLCLR component is a straighforward .NET assembly - with some minor tagging to identify it as a stored procedure, and using SQL datatypes in all its inputs/outputs (Listing 1). Once compiled, it's copied to a local directory on the SQL server, registered as an assembly and a procedure, and you're good to go. There are some security concessions to make - allowing CLR code to run and setting the project database to allow CLR code to access external resources. I may look into tightening security on it more later, but this works for now. The next step is to integrate this into a part of the player page, so I'll have a record of who's on what channels, and when. Listing 1 (VB.NET) ' ============================================================================== ' VB.NET SQLCLR to query an external web service (MaxMind) for geographic data ' 06/13/2006 Tim Shay ' ============================================================================== Imports System.Data Imports System.Data.SqlClient Imports System.Data.SqlTypes Imports System.Net Imports System.IO Imports Microsoft.SqlServer.Server Partial Public Class StoredProcedures _ Public Shared Sub MMGeoLocate( _ ByVal ClientIP As SqlString, _ ByRef CountryCode As SqlString, ByRef RegionCode As SqlString, _ ByRef City As SqlString, _ ByRef Latitude As SqlDecimal, ByRef Longitude As SqlDecimal, _ ByRef ErrCode As SqlString) Dim ResponseTxt As String = "" Dim ParsedResult() As String 'Lat/Lon will return as zero if any issues arise in the geo-location. Latitude = 0 Longitude = 0 'Create an HttpWebRequest, Retrieve results through HTTPWebResponse ' - through StreamReader - into a String 'I've replaced my MaxMind license key with a bogus one for this sample. 'You'd need your own account to use this service. Dim HTTPReq As HttpWebRequest = _ WebRequest.Create( _ String.Concat("http://maxmind.com:8010/b?l=xxyyzz&i=", ClientIP)) 'Timeout - 10 seconds HTTPReq.Timeout = 10000 Try Dim StrmRdr As New StreamReader(HTTPReq.GetResponse().GetResponseStream()) ResponseTxt = StrmRdr.ReadToEnd() StrmRdr.Close() Catch WebX As WebException If WebX.Status = WebExceptionStatus.Timeout Then ErrCode = "HTTP_TIMEOUT" Else ErrCode = Left(WebX.Message, 255) End If End Try 'Response from this site is comma-delimited ASCII ' - 5 elements on success, and 6 on failure. 'If the response is anything but 5 fields, 'it's an error and only the ErrCode is set. ParsedResult = Split(ResponseTxt, ",") Select Case ParsedResult.Length Case 5 CountryCode = ParsedResult(0) RegionCode = ParsedResult(1) City = ParsedResult(2) Try Latitude = ParsedResult(3) Longitude = ParsedResult(4) Catch ex As Exception End Try Case 6 ErrCode = ParsedResult(5) Case Else ErrCode = Left(ResponseTxt, 255) End Select End Sub End Class Listing 2 (SQL Server 2005) -- ============================================================================== -- Configure, Register and Test SQLCLR External Assemblies for MMGeoLocate -- 06/13/2006 Tim Shay -- ============================================================================== USE s112DB GO -- Configure the server to allow CLR procedures sp_configure "clr enabled", 1 reconfigure GO -- The drops are not normally needed --DROP PROCEDURE MMGeoLocate --DROP ASSEMBLY s112DBCLR --GO -- The alter gives this database a set of permissions that includes web access ALTER DATABASE s112DB SET TRUSTWORTHY ON GO -- Register the assembly (first manually copy the VB.NET DLL to a local dir) CREATE ASSEMBLY s112DBCLR FROM 'c:\Station112\sqlclr\s112DBCLR.dll' WITH PERMISSION_SET = EXTERNAL_ACCESS GO -- Create the stored procedure CREATE PROCEDURE MMGeoLocate ( @ClientIP nvarchar(255), @CountryCode nVARCHAR(3) OUT, @RegionCode nVARCHAR(50) OUT, @City nvarchar(255) OUT, @Latitude Decimal (18,10) OUT, @Longitude Decimal(18,10) OUT, @ErrCode nvarchar(255) OUT ) AS EXTERNAL NAME s112DBCLR.[s112DBCLR.StoredProcedures].MMGeoLocate GO -- -- Test code to run the procedure and return results in the query window -- DECLARE @ClientIP nvarchar(255) DECLARE @CountryCode nVARCHAR(3) DECLARE @RegionCode nVARCHAR(50) DECLARE @City nvarchar(255) DECLARE @Latitude Decimal (18,10) DECLARE @Longitude Decimal(18,10) DECLARE @ErrCode nvarchar(255) SET @ClientIP = '24.123.178.202' EXEC MMGeoLocate @ClientIP, @CountryCode OUTPUT, @RegionCode OUTPUT, @City OUTPUT, @Latitude OUTPUT, @Longitude OUTPUT, @ErrCode OUTPUT SELECT @ClientIP, @CountryCode, @RegionCode, @City, @Latitude, @Longitude, @ErrCode Help is everywhere on the web, and I spend a good bit of time hunting it down. For the geo-locator component, the following were invaluable resources: http://msdn.microsoft.com/sql/default.aspx?pull=/library/en-us/dnsql90/html/mandataaccess.asp http://aspnet.4guysfromrolla.com/articles/122204-1.aspx http://www.devx.com/codemag/Article/31193/0/page/4 http://www.novicksoftware.com/coding-in-sql/Vol3/cis-v3-N15-sqlclr-stored-procedure-using-external_access.htm