# Tuesday, November 20, 2007

I just saw these and thought they were worthy of linkage

Clinic 2806: Microsoft® Security Guidance Training for Developers.

Clinic 2807: Microsoft® Security Guidance Training for Developers II.

There is a good breadth of topics covered, and the price is right :-)

Tuesday, November 20, 2007 11:37:00 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, October 14, 2007
It was great being able to have the opportunity to elucidate my thoughts on this matter formally at SQL Down Under Code Camp '07.

For completeness, here are my slides: The Zen of T-SQL SDU CC.ppt (128.5 KB)

I really enjoyed meeting so many nice and very clever folks.  Thanks to Greg and all involved in putting on the Code Camp, what a really great event!

For the record, the image is of Kasprowicz catching Pietersen at NatWest Challenge Final, The Oval, 2005.

:-)

Sunday, October 14, 2007 10:25:08 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, July 12, 2007

How to start?
You will need several assemblies.  This is because to reach the level of decoupling that is desired, the pipeline has a certain pattern of dependencies between projects.  I’m not sure if I am subconsciously not objecting to it or actually actively like this now, was not always the way.

A pipeline?
Yes, you need one. 

What is a pipeline?
It’s a series of folders that live somewhere (does not have to be under your application's path) and each of the assemblies have their place in the structure.  The folders will look like this:

It’s probably a good idea to build one now in your project tree and set the build output as you go.

There is a graphic explaining the pipeline on the CLR Add-In team blog (with nice colours), it is also in the Orcas MSDN under the title: "Pipeline Development Requirements".  The MSDN one has the addition of lines to indicate the static dependancies.

I've chosen to show it differently in my graphics (don't say a word!) to indicate the order of it all coming together as well as the references.  In the graphic the arrow lines illustrate the dependancies between the projects.

Also, I make reference to the sample code throughout this post.  Download link is at the bottom.

Step 1: Define Contracts

The first step is to define the contracts in your contracts assembly and DTOs in your DTO’s assembly.

Your contract should be one interface per kind of add-in you will support.  These interfaces need to inherit System.AddIn.Contract.IContract and be decorated with System.AddIn.Pipeline.AddInContractAttribute.

Types in the DTO that you wish to pass over the boundary will need to be serializable.

Jason He’s example of a Paint.NET Add-In (link below) takes a different path, by adding the extra types in the Add-In View, adding more wrappers.  His approach may have advantages that I have not discovered yet, but it reminds me of some of the dancing you have to do when for example you have the same type in a Web Reference and a binary reference in the same project. 

My preference is then to make a behavior-free separate assembly that anyone can take a dependency on safely.  This is the reason for including a DTO project.  I also like having the DTO types there to do as a [DataContract] does in WCF.  This will allow the Add-In contract to remain static if the host side changes it’s implementations of the DTO equiv. types.

Change the project properties of the Contracts project to build to: ..\Pipeline\Contracts\

Also note, for types that take a dependency on the DTO project, set the Copy Local property of the reference to False.  This is to keep the pipleline path clean.  i.e. we don’t actually want a copy of the DTO assembly in the \pipeline\contracts\ path!  This will slow our discovery and generate warnings as the Add-In infrastructure tries to examine it for contracts.

Step 2: Host View and Add-In View

Add two new assemblies:  host view and add-in view
Each has a public abstract class that mirrors the contract interface but does not reference it.

Host view does not even need a reference to System.AddIn.

When building the Add-In View, be sure to:

  • Apply System.AddIn.Pipeline.AddInBaseAttribute
  • Set the project to build to ..\Pipeline\AddInViews\

Step 3:  Host Adaptor and Add-In Adaptor

Add two more assemblies:  host adaptor and add-in adaptor

Add-in adapter will have one AddinToContractAdapter class for each Add-In type and the Host adapter has one ContractToHostViewAdapter class for each Add-In type.

The AddinToContractAdapter descends from System.AddIn.ContractBase and implements the contract for the Add-In

The ContractToHostViewAdapter descends from the Abstract class in the Host View for the Add-In.

Set the build output path of the Host Side adapter to: ..\Pipeline\HostSideAdapters\
And set the build output path of the Add-In Side adapter to: ..\Pipeline\AddInSideAdapters\

The purpose of these adapters is too marshal calls between the instances of your IContract's and should just look like wrapper code.

Step 4: Build the Add-Ins

Every Add-In needs to take a dependency on the Add-In View project and the DTO project.  Be sure to set their Copy Local = False in the reference properties.

Each Add-In also needs to descend from the abstract class in the Add-In View project, implement overrides, and to be decorated with System.AddIn.AddInAttribute.

The AddIn Attribute is the key to how the Add-In will be seen by the host so pay attention to the parameters on the constructor.

Set the build output path of each Add-In to: ..\Pipeline\AddIns\<addinName>\

I should mention that the Add-In's in the sample code below are just stubs to show the complete loop.  The Book Library Add-In returns empty objects of the prescribed types, the other two throw an Exception.  This is to show error handling.

Step 5:  The Add-In Host

Take a reference to the Host View and Dto projects, this time it is OK to have the reference Copy Local.

In the attached example the Book Library add-in returns empty objects of the designed type, however the other two (DVD Library and CD Library) throw an Exception for each operation. 

By the end of the process, the project will look like this:


Trouble shooting & Error Handling

Just skiming over this topic, but it is wise to wire up a handler to AppDomain.UnhandledException for the app domain that will run your Add-Ins, and Application.ThreadException (Windows Forms examples) as well as wrapping calls into the Add-In with a Try... Catch block. 

If you are trying to work out why your AddIns are not being discovered, remember that:

  • AddInStore.Rebuild()
  • AddInStore.RebuildAddIns()
  • AddInStore.Update()
  • AddInStore.UpdateAddIns()

...all return an array of strings that can be examined to determine how the AddIn discovery went.

Source Code:

The source code for this example is available for download from the following link:

LibraryAddInDemoCode_deepdark.net.zip (152.81 KB)

It requires Visual Studio Codename Orcas Beta 1.

Summary:

There are a couple of steps to implementing the new System.Addin stuff, but none of it is hard!

...and considering that it replaces a lot of very untidy and error-prone Reflection code that we had to do in prior versions of the framework I think this is a great addition to the toolbox.

This post is not meant to be a hardcore reference, just the total of my experience with this technology to date.  If you have any feedback please don't hesitate to contact me by email or leaving a comment on this post.

Sources:

Listening to: The Chillout Sessions 3

Thursday, July 12, 2007 5:18:15 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, April 04, 2007

An MVP they call Brian referred me to a new Blog/RSS Feed client called FeedGhost.

It scratches my itch for a feed reader that can sync between multiple PCs through a subscription service, but the most impressive feature I have found so far is the UI.  It has set a new high water mark for me in the smartclient space. 

Check out the screen shots - but once installed you realize the screenshots don't do it justice. 

The timing of this news couldn't be better for me because I was reading my feeds on my "Beta Bliss" laptop - Vista RC1 & Office 2007 Beta 2 TR, and office expired 1st of April so I was in the market for a new feed reader.  I love it when things just come together :-)

Wednesday, April 04, 2007 11:06:11 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, February 21, 2007
Rob Farley posted a very interesting codegen post on scripting objects this morning, and as a reforming codegen junky I just couldn't let it go without comment :-)

Firstly, I modified his query as so:

select quotename(si.name) as "@IndexName", quotename(ss.name) AS "@SchemaName", quotename(so.name) AS "@ObjectName",
    stuff((select ',' + quotename(sc.name)
            from sys.index_columns sic
            join sys.columns sc
                on sc.column_id = sic.column_id
            where so.object_id = sic.object_id
                and sic.index_id = si.index_id
                and sc.object_id = so.object_id
            order by sic.key_ordinal
            for xml path('')),1,1,'') as "@IndexColumns"
from sys.indexes si
join sys.objects so
    on so.object_id = si.object_id
join sys.schemas ss
    on ss.schema_id = so.schema_id
where so.type = 'U' and si.type = 1
for xml path('index'), root('indexes')


Things I'll point out:
  • Adding the extra for xml clause, this time specifying a better row element name than 'row' and also adding a document node
  • Once the outter for xml clause is in place, we can alias the columns using @ to have them come out as elements in the results
We can feed the results of that query straight into the following XSLT:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"
/>
   
    <xsl:template match='/'>
    <xsl:apply-templates select ='indexes/index'
/>
    </xsl:template>

  <xsl:template match='index' >
create index <xsl:value-of select='@IndexName'
/>
  on <xsl:value-of select='@SchemaName'
/>.<xsl:value-of select='@ObjectName'/> (<xsl:value-of select='@IndexColumns'/>)
  </xsl:template>
 
</xsl:stylesheet>

I'm not claiming this method is superior, just different, which I think is in keeping with the spirit of Rob's post :-)  and I have learned more about the improvements of the for xml clause in SQL Server 2005 in the process.

I'll leave final judgment on the utility of this approach as an exercise to the reader; my instinctive reaction is to include it as a build step to help you snapshot schema changes between check-ins, or as Rob suggests to take objects from one database and create slightly different objects in another database – there are no wrong answers and if you think of something interesting please leave a comment :-)

Grab the source files here: ScriptObjects.zip (.78 KB)
Wednesday, February 21, 2007 6:32:28 PM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [2]  | 
# Wednesday, November 15, 2006

I just thought it would be more sense to provide a link to the files mentioned in my last post.  Grab them if you are interested.

Wednesday, November 15, 2006 9:45:46 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [0]  | 
# Friday, September 01, 2006
Hows that for a long title? 

So there is a new version of Visual Studio (in CTP at time of writing) called Visual Studio Team Edition for Database Professionals - its aimed at people who might associate themselves with the title Database Professional.  I gotta say, it looks like a really good solution to some problems.

I attended a cabana session at Tech.Ed (Tech.James?) this year hosted by Greg Low on data generation in the product, and during the presentation it came up that it would be nice to have custom generator for Australian-specific data... so I thought I'd take a stab at it.

Below is a screencap of the kind of random data my generator will spit out.  Handy for columns where a check constraint may be forcing a given format for the data.  The format of the phone numbers is configurable by a property and the rows are conistant for a location so that if we generate a Vic address it will have a valid Vic phone number etc.



The good news is its really easy to do.  Even at this early stage the product has some pretty reasonable doco on what to do to write your own generators.

So my custom generator is available for download by clicking on this link

To install it on your copy of vsdbpro:
  1. Copy the DLL from that zip into the following path on your PC: 
    [Program Files]\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\
  2. Edit the config file at:
    [Program Files]\Microsoft Visual Studio 8\DBPro\Microsoft.VisualStudio.TeamSystem.Data.Extensions.xml with a suitable XML editor and add the following line:
    <type>deepdark.net.PersonalDetails, AustralianDetails, Version=1.0.0.0, Culture=neutral, PublicKeyToken=341d0bd35c6f7d28</type>
  3. Restart Visual Studio, you should see a new generator called Personal Details in the list.

The source code is hardly going to start a revolutiuon, but I can make it available if there is any interest - just let me know.
Friday, September 01, 2006 9:16:57 AM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
# Tuesday, August 15, 2006
Just a quick note...

Adobe Acrobat reader is slow... FoxIt Reader is Fast

Nothing in it for me, just sharing the good vibes :)  Thank you FoxIt

Tuesday, August 15, 2006 9:06:44 PM (AUS Eastern Standard Time, UTC+10:00)  #    Disclaimer  |  Comments [1]  | 
# Thursday, January 12, 2006

Tracking stray connections using profilerTimes when this can come into play is in multithreaded apps, or apps where you may be supporting simultanious users like in an ASP.NET application. 

 

Generally any time you are asking resources from the server it should be using the Try... Catch... Finally pattern for allocating server resources and releasing them as soon as you know you can do without them.  (Nod to Andy Rich on Deterministic Finalization)


One thing that is going to help with this however is to set the appname in your connection string (Application Name={1};) for filtering the Profiler results.


So here is a Profiler trace useful for keeping an eye logins, logouts and stored procs executed inbetween:


Download: deepdark.net_Connection_Monitor_20060112.zip

Thursday, January 12, 2006 12:45:32 AM (AUS Eastern Daylight Time, UTC+11:00)  #    Disclaimer  |  Comments [1]  |