Thursday, August 27, 2009

Cost of Raising an Exception

Here’s an interesting bit of code that highlights the true costs when raising exceptions:

Sub Main()

     Dim sw As New Stopwatch
     sw.Start()
     Dim obj As String
     For i As Integer = 0 To 10000
         Try
             Dim myObj As Object = Guid.NewGuid

             obj = myObj

         Catch ex As Exception

         End Try
     Next

     sw.Stop()
     Console.WriteLine(sw.ElapsedMilliseconds)
     sw.Reset()
     sw.Start()
     For i As Integer = 0 To 10000
         Try
             Dim myObj As Object = Guid.NewGuid

             obj = CType(myObj, Guid).ToString

         Catch ex As Exception

         End Try

     Next

     sw.Stop()
     Console.WriteLine(sw.ElapsedMilliseconds)
     Console.ReadLine()
End Sub

The timings on my laptop were 30000ms for loop 1 i.e. where we’re trying to cause exceptions and just 6ms for loop 2 where we casting types correctly!

Wednesday, August 26, 2009

Filestreams and freetext search

File streams in SQL 2008 provide a nice way of storing large blobs of data in the database without impacting database size. However creating them manually is not something that interests most programmers who want to use SMO.

So how can we create these through code?

The first thing you need to do is enable FILESTREAMS if they’re not already. Do this from SQL Server Configuration Manager:

image

Select Properties from the action menu

image

Enable Filestreams & restart the database if needed.

You now need to enable Filestream access (Server Properties->Advanced) on the server from SQL Management studio.

image

We’re now ready to start creating a database with a filestream and some tables:

Create The Database:

You can look at the article by S.Vinothkumar or use the code based on his work below:

Sub CreateDatabaseWithStream(ByVal dbName As String, ByVal serverName As String, ByVal dbPath As String)

    Dim mdfFile As String = IO.Path.Combine(dbPath, dbName & ".mdf")
    Dim ldfFile As String = IO.Path.Combine(dbPath, dbName & "_log.ldf")
    Dim FilesDir As String = IO.Path.Combine(dbPath, dbName & "_filestream")

    Dim server As New Microsoft.SqlServer.Management.Smo.Server(serverName)
    Dim database As Database = New Database(server, dbName)
    database.FileGroups.Add(New FileGroup(database, "PRIMARY"))
    database.FileGroups.Add(New FileGroup(database, "FileStream" & dbName, True))
    Dim dtPrimary As DataFile = New DataFile(database.FileGroups("PRIMARY"), "PriValue", mdfFile)
    database.FileGroups("PRIMARY").Files.Add(dtPrimary)
    database.FileGroups("FileStream" & dbName).Files.Add(New DataFile(database.FileGroups("FileStream" & dbName), "FileStream" & dbName & " Values", FilesDir))
    Dim logFile As LogFile = New LogFile(database, "PriValue_log", ldfFile)
    database.LogFiles.Add(logFile)
    database.Create()
    database.Refresh()
End Sub

Add A Table:

we now need to create a table with some columns, a data column and a type column.

The function below does this, the important things to remember are to set the id as a unqiue key.

Sub CreateTable(ByVal db As Database, ByVal tableName As String)

      Dim tb As New Table(db, tableName)
      Dim col As Column
      col = New Column(tb, "rowid", DataType.UniqueIdentifier)
      col.Identity = False
      col.Nullable = False
      col.RowGuidCol = True
      Dim Dc As DefaultConstraint = col.AddDefaultConstraint("DF_RowGuid")
      Dc.Text = "NEWID()"
      tb.Columns.Add(col)
      tb.Create()

      Dim idx As New Index(tb, "AK_" & Now.Ticks)
      Dim icol1 As IndexedColumn
      icol1 = New IndexedColumn(idx, "rowid", False)
      idx.IndexedColumns.Add(icol1)
      idx.IndexKeyType = IndexKeyType.DriUniqueKey
      idx.IsClustered = True
      idx.Create()

      col = New Column(tb, "filedata", DataType.VarBinaryMax, True)
      col.Identity = False
      col.Nullable = True
      tb.Columns.Add(col)
      col = New Column(tb, "ext", DataType.VarChar(255))
      col.Identity = False
      col.Nullable = True
      tb.Columns.Add(col) 
      tb.Alter()
      db.Alter()
  End Sub

Create The Text Index:

Once we have our database then it’s time to create a our freetext index. You can do this simply by create a new freetext catalog for our new database, this is well documented here but in summary is creates a new catalog against the specified database.

dim ftc as New FullTextCatalog(db, "Test_Catalog")
ftc.IsDefault = True
ftc.Create()
Dim fti As FullTextIndex
fti = New FullTextIndex(tb)
Dim ftic As FullTextIndexColumn
ftic = New FullTextIndexColumn(fti, "filedata")
ftic.TypeColumnName = "ext"
ftic.Language = "English"
fti.IndexedColumns.Add(ftic)
fti.ChangeTracking = ChangeTracking.Automatic
fti.UniqueIndexName = idx.Name
fti.CatalogName = "Test_Catalog"
fti.Create()

So with everything setup the next thing to do is load your data into the table – make sure that you set the extension and the text indexing engine will do the rest. Then just use contains TSQL contains to mine the text catalog.

DECLARE @SearchWord nvarchar(30)
SET @SearchWord = 'test'
SELECT id,name
FROM files
WHERE CONTAINS(filedata, @SearchWord);

Thursday, August 06, 2009

Rail Time!

If you used MyRail for the iPhone then check this link out

http://railtimes.it-dev.co.uk/railtimes/

image

It’s a web app with a simple interface that I knocked together to make searching train times simple and flexible.