February 2007 - Posts

Last week I added another Dutch language screen cast to my web site about Windows Workflow Foundation. The topic time is external communications.
 
 
Enjoy!
 
with no comments
Filed under: , , , ,
Just in case this slipped by Smile
 
 
Enjoy!
 
with no comments
Filed under: , ,
Reflector by Lutz Roeder is probably the tool I use most often when developing .NET code, well just after Visual Studio 2005 anyway. And now there is a new version, 5, out. Still free, still excellent. Highly recommended.
 
Enjoy!
 
with no comments
Filed under: , , , , , ,
SQL CLR is pretty cool and lets you quickly do lots of things that are hard, if not impossible, to code in TSQL. But if you want to create generic code you sometimes need to know the context that the code is running under. The problem I had was creating a generic table update trigger and knowing the table that was updated.
 
During the execution of an update trigger you can get your hands on the new data using the Inserted temporary table so the data is there but there is no way of knowing the original table name, it just isn't exposed in any way. Well that was a bit of a problem and it turns out I wasn't the first one to run into this issue as web search pointed me to a number of similar questions but no answers. One possible solution I did find was using a <TableName>Id convention and making sure it was the first column every time. Not very pretty and not usable in my case as I have to work against an existing database.
 
So the only solution I could come up with is comparing the table schema of the Inserted table against the known tables in the database. Maybe not the prettiest solution but it works. The first time a trigger fires the code caches the schema for each table in a dictionary. Afterwards I just compare the schema of the Inserted table against the cache of schema's. Of course there is a catch, if your database contains two tables with identical structure they will produce the same schema, I change the table name, and the code will fail. As I don’t believe this is a common occurrence I decided I could live with this solution. But it anyone has a better solution that works with all existing databases I sure would like to hear about it Smile
 
So the code is actually pretty simple:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using Microsoft.SqlServer.Server;
 
 
publicpartialclassTriggers
{
    // Enter existing table or view for the target and uncomment the attribute line
    [SqlTrigger(Name = "Trigger1", Target = "TestTable", Event = "FOR UPDATE")]
    publicstaticvoid Trigger1()
    {
        string schema = GetSchema("Inserted");
        string tableName = DetermineTableNameFromSchema(schema);
 
        SqlContext.Pipe.Send(string.Format("TableName is {0}", tableName));
    }
 
 
    privatereadonlystaticDictionary<string, string> _schemas = newDictionary<string, string>();
 
    privatestaticstring DetermineTableNameFromSchema(string schema)
    {
        string result = "";
 
        if (_schemas.Count == 0)
        {
            // First time, fill the collection with schema info
            using (SqlConnection conn = newSqlConnection("context connection=true"))
            {
                string sql = "Select * from INFORMATION_SCHEMA.Tables where TABLE_TYPE = 'BASE TABLE'";
                SqlDataAdapter ds = newSqlDataAdapter(sql, conn);
                DataTable tables = newDataTable();
                ds.Fill(tables);
 
                foreach (DataRow row in tables.Rows)
                {
                    string tableSchema = row["TABLE_SCHEMA"].ToString();
                    string tableName = row["TABLE_NAME"].ToString();
                    string fullName = string.Format("[{0}].[{1}]", tableSchema, tableName);
                    string tempSchema = GetSchema(fullName);
                    _schemas.Add(tempSchema, fullName);
                }
            }
        }
 
        _schemas.TryGetValue(schema, out result);
 
        return result;
    }
 
 
    privatestaticstring GetSchema(string tableName)
    {
        string schema = "";
        using (SqlConnection conn = newSqlConnection("context connection=true"))
        {
            string sql = string.Format("select * from {0}", tableName);
            SqlDataAdapter ds = newSqlDataAdapter(sql, conn);
            DataTable dt = newDataTable();
            ds.FillSchema(dt, SchemaType.Source);
 
            // Rename the table as we want to match it against the inserted table
            dt.TableName = "Inserted";
            // Always remove the primary key as it won't be present on the Inserted table
            dt.PrimaryKey = null;
 
            StringWriter sw = newStringWriter();
            dt.WriteXmlSchema(sw, false);
            schema = sw.ToString();
            sw.Close();
        }
 
        return schema;
    }
}
 
Enjoy!
 
 
 
with no comments
Filed under:
SQL Server CLR integration is pretty cool Smile allowing me to write .NET code and have it execute in SQL Server, for example as a stored procedure. Not that I would want to write every stored procedure using .NET code but for some of them it sure is a lot easier.
 
To enable it you need to reconfigure SQL Server a bit though. You need to enable CLR integration using the sp_configure sproc. Just don’t forget to execute a Reconfigure when done.
 
Just use:
sp_configure 'clr enabled', 1
go
reconfigure
go
And you are ready to go Smile
 
Enjoy!
 
with no comments
Filed under: ,
If you are using Actions Panes in a VSTO Excel add-in you might have seen the following behavior. You create an new ActionPane, derived from UserControl, and add it to the Workbook ActionsPane.Controls collection. It shows up nicely so you think you are done.
 
Now the user creates a new Spreadsheet using File/New. Note that the ActionsPane disappears and remains hidden until the user reactivates it using View/Task Pane or Ctrl+F1.
 
So how do you automatically display the TaskPane when the user switched back to the original document? You need to add the following code to the ThisWorkbook type:
 
PrivateSub ThisWorkbook_WindowActivate(ByVal Wn As Window) HandlesMe.WindowActivate
    Application.DisplayDocumentActionTaskPane = True
EndSub
 
Enjoy!
 
with no comments
Filed under: , ,
Something I often see in code is that parts of it are contained in the following construct:
#If DEBUG Then
   ' Some code
#End If
 
Nothing wrong with that but often the code is the complete function body leaving an empty function in release mode. Now the JIT optimizer will make short work of it so there isn't a big performance penalty but why make it go through these steps in the first place.
 
Another way way of doing so is using the Diagnostics.Conditional attribute. This can be applied to some function and removes all calls to it, so much nicer Smile
 
<Diagnostics.Conditional("DEBUG")> _
Public Sub OnlyHereInDebugMode()
   ' Some code
End Sub
 
To see that the function call is really removed just open reflector and compare the release and debug builds.
 
Enjoy!
 
with 4 comment(s)
Filed under: ,
In C# they have a thing called relaxed delegates that allow you to create an event handler with all parameter types as object and still be able to bind them to an event. Nice Smile
 
In VB we don't have the same thing, the parameters must match exactly. So the following piece of code doesn’t work Sad
 
Imports System.Reflection
Imports System.Windows.Forms
 
Module Module1
 
    Sub Main()
        Dim demo AsNew EventDemo
        demo.HookEvent()
        demo.FireEvent()
    EndSub
EndModule
 
 
PublicClass EventDemo
    Private _textBox AsNew TextBox
 
    PublicSub HookEvent()
        AddHandler _textBox.TextChanged, AddressOf MyEventHandler
    EndSub
 
    PublicSub FireEvent()
        _textBox.Text = "Some text"
    EndSub
 
    Sub MyEventHandler(ByVal sender AsObject, ByVal e AsObject)
        Console.WriteLine("Event fired, sender = '{0}', e = '{1}'", sender.GetType().FullName, e.GetType().FullName)
    EndSub
EndClass
 
So is there no way to use a generic event handler with all parameters defined as object? Actually there is, its just a bit harder to do. Change the HookEvent to the following and it will work just fine:
 
PublicSub HookEvent()
    Dim eventInfo As EventInfo
    Dim methodInfo As MethodInfo
    Dim dlg As [Delegate]
    eventInfo = _textBox.GetType().GetEvent("TextChanged")
    methodInfo = Me.GetType().GetMethod("MyEventHandler")
    dlg = [Delegate].CreateDelegate(eventInfo.EventHandlerType, Me, methodInfo)
    eventInfo.AddEventHandler(_textBox, dlg)
EndSub
 
Not exactly the prettiest way of doing it but when you need to it will work Smile. Lets just hope that relaxed delegates make their way into VB 9 so we can just use the AddHandler syntax, after all it is so much cleaner.
 
Enjoy!
 
with no comments
Filed under: ,
www.sdn.nl
 
The Software Developer Network (SDN) has begun planning for its 16th annual Software Developer Conference (SDC) to be held in The Netherlands on September 17 and 18, 2007.
We hereby invite you to submit proposals to be considered for participation as a speaker on this upcoming event.
 
Software Developer Conference
In May 2006, Software Developer Network held its 15th SDC in a row, again presenting the attendees with the latest techniques available. SDC 2006 was attended by over 400 professional software developers. 38 domestic and international speakers presented over 100 sessions on various topics.
 
Request for Speakers
SDN is looking for IT professionals who are interested in speaking at SDC 2007. We ask that you provide an outline of your proposed topic(s) and a brief description of your background (bio). The Conference will have introductory and advanced sessions on C#, Visual Basic.NET, ASP.NET, DotNetNuke, Delphi, Database Technologies and other (general) topics of interest. The executive committee will review all submissions and contact candidates. Speakers who are able to speak on more than one subject and on more than one programming language are preferred.
Speakers at SDC 2007 will be fully reimbursed for all travel and hotel costs, including meals.
 
Submitting proposals
For submitting your proposals we ask you to use the submission forms that can be downloaded from www.sdc.nl/cfs. This zip-file also contains more detailed information about Software Developer Network and SDC 2006.
The closing date for submitting proposals is April 30, 2007.
 
Please forward this message to anybody who might also be interested.
Mark Blomsma (A fellow Dutch C# MVP) has just published an interesting article about integrating the Amazon Mechanical Turk into a Windows Workflow Foundation.
 
 
Enjoy!
 
with no comments
Filed under: , ,
Its always nice to see that people enjoy utilities I wrote. One of those ParseLocals is something I wrote years ago for work in Visual FoxPro and checks the current source file for missing variable declarations. Guess people are still using it because I had a few emails about it recently. Kurt Graßl and Peter Crabtree mailed me with some changes that I have included in the current source.
 
 
Enjoy!
 
 
with no comments
Filed under:
If you want to run Visual Studio 2005 on Windows Vista you might want to take a close look at the following two lists. They list some of the issues you might run into. In other words, make sure you can live without.
 
Check for running with elevated administrator permissions at http://msdn2.microsoft.com/en-us/vstudio/aa964140.aspx and additionally for running with normal user permissions at http://msdn2.microsoft.com/en-us/vstudio/aa972193.aspx.
 
Take good care :-)
 
with no comments
Filed under: , , , , ,