Skip to content

Home

Running MSTest without Visual Studio – Gallio to the rescue

In some cases it can be useful to quickly run your Microsoft unit tests on a machine where Visual Studio is not installed. For example on an end-user machine and/or during acceptance testing. Microsoft unit tests have a great integration with Visual Studio and Team Foundation Server, but unfortunately the unit tests cannot be run as a standalone application.

I saw there was an open-source adapter for NUnit, called Microsoft Team System NUnit Adapter from Exact Magic Software that can run Microsoft unit tests inside NAnt. For my unit tests I had some problems with the ExpectedException attribute. Then I noticed there is a project called Gallio and it worked like a charm and it can do a lot more! I noticed that today a new version has been released, namely Gallio v3.0.4.

Gallio is a extensible , open and neutral test automation platform. It provides tools and services needed to run and manipulate tests written using a wide range of other frameworks. Gallio can run tests from

and it can integrate with the following tools

To run the the tests there is a command-line runner, called ‘Echo’ and a graphical user-interface, called ‘Icarus’.

Gallio

Introduction to the Unity Application Block

The unity application block is a dependency injection container with support for constructor, property and method call injection. It simplifies the Inversion of Control (IoC) pattern and the Dependency Injection (DI) pattern. The Unity application block can be found on CodePlex.

The unity application block has two important methods for registering types and mappings into the container, namely RegisterType and RegisterInstance.

Method Default Lifetime Explanation
RegisterType Transient Lifetime Container will create a new instance on each call to Resolve
RegisterInstance Container-controller lifetime Instance has the lifetime of the container

Below you find an example where we map the ILogger interface to ConsoleLogger (implements ILogger).

UnityContainer container = new UnityContainer();
container.RegisterType<ILogger, ConsoleLogger>();
ILogger logger = container.Resolve<ILogger>();

Assume you have the following class that contains a dependency to ILogger as a parameter on the constructor.

public class MyClass
{
   ILogger _logger;

   public MyClass(ILogger logger)
   {
      _logger = logger;
   }
}

If we use the Resolve method of UnityContainer it will automatically inject the ILogger (ConsoleLogger) object. This is called constructor injection.

UnityContainer container = new UnityContainer();
container.RegisterType<ILogger, ConsoleLogger>();
MyClass myClass = container.Resolve<MyClass>();

You can also map multiple types for the same interface. In that case you can use a key as a parameter.

UnityContainer container = new UnityContainer();
container.RegisterType<ILogger, ConsoleLogger>("console");
container.RegisterType<ILogger, EventLogger>("event");

If you now try to resolve MyClass you will get an exception, because it cannot resolve which type (ConsoleLogger or EventLogger) to use. Therefore you can use the Dependency attribute where you can denote a key. For example:

public class MyClass
{
   ILogger _logger;

   public MyClass([Dependency("console")] ILogger logger)
   {
      _logger = logger;
   }
}

Below you find an example of property injection:

public class AnotherClass
{
   ILogger _consoleLogger;
   ILogger _eventLogger;

   [Dependency("console")]
   public ILogger ConsoleLogger
   {
      get { return _consoleLogger; }
      set { _consoleLogger = value; }
   }

   [Dependency("event")]
   public ILogger EventLogger
   {
      get { return _eventLogger; }
      set { _eventLogger = value; }
   }
}

Note that you can also map and register your types through a configuration file.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity>
    <containers>
      <container>
        <types>
          <type name="console" type="IStaySharp.UnitySample.ILogger, IStaySharp.UnitySample" mapTo="IStaySharp.UnitySample.ConsoleLogger, IStaySharp.UnitySample" />
          <type name="event" type="IStaySharp.UnitySample.ILogger, IStaySharp.UnitySample" mapTo="IStaySharp.UnitySample.EventLogger, IStaySharp.UnitySample" />
        </types>
      </container>
  </containers>
  </unity>
</configuration>

The following code shows you how to use a configuration file with UnityContainer.

UnityContainer container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers.Default.GetConfigCommand().Configure(container);

ILogger logger = container.Resolve<ILogger>("console");

Edit and Continue not supported on 64-bit target machine

When trying to edit some code during debug, I received the following dialog of Visual Studio:

EditContinue64_2

It appears that the edit and continue feature is not supported when the target is a 64-bit application. On this page you find a nice overview of the scenarios where the edit and continue features are not supported. To resolve the problem, you have to set the target to x86, which can be found in the project properties.

BuildSettingsPlatform_2

Running a x86 libray on a x64 machine

In my current sample project when the runtime tried to access the MyMeta library (see following post) I always get the following FatalExecutingEngineError exception:

FatalExecutionEngineError_2

It turns out that the problem is that the MyMeta library is compiled under a x86 platform whereas the application is running on a x64 platform. In the properties settings of your visual studio project you have to set the platform target to x86! It was set to 'Any CPU', but now everything works fine.

BuildSettingsPlatform_2

Component Dropper v0.9 - Add-in for Visual Studio

Component Dropper is a component that resides in the toolbox of VS.NET and enables you to choose a component (controls, datasets, providers, components, etc.) from the assemblies that are referenced in the current project.

In Visual Studio .NET you can auto populate the controls in the toolbox by setting the AutoToolboxPopulate property to true in menu Tools -> Options -> Windows Forms Designer.

AutoToolboxPopulate_2

Component Dropper is an alternative way for dropping a component on the designer surface. It gives you a dialog with all the components that reside in the assemblies that are referenced in the current project. This means that it is not limited to the assemblies that reside in the current solution. This way you can easily browse and search throughout the assemblies and controls, this is very handy if you have bunch of assemblies and controls. There is never a need to refresh the toolbox, because it dynamically searches throughout the references in the current project.

componentdropper09_4

Download: RazorToolbox

If after installation you don't see the component dropper appearing in the toolbox, you can simply drag-and-drop the IStaySharp.RazorToolbox.dll to the toolbox.

Any suggestions or remarks are welcome!

Programmatically creating tables in SQL Server using .NET and SMO

SMO (SQL Server Management Objects) is a .NET based object library for programming all aspects of managing Microsoft SQL Server. Replication Management Objects (RMO) is another library that encapsulates SQL Server replication management.

SMO assemblies are shipped with SQL Server 2005 and can be used to connect with SQL Server 7, 2000 or 2005. The assemblies are located in the following folder C:\Program Files\Microsoft SQL Server\90SDKAssemblies.

  • Microsoft.SqlServer.Smo.dll
  • Microsoft.SqlServer.ConnectionInfo.dll
  • Microsoft.SqlServer.SmoEnum.dll
  • Microsoft.SqlServer.SqlEnum.dll

With SMO you can do all kind of management on a SQL Server, namely: tables, columns, indexes, stored procedures, service broker, backup and restore, managing users/roles and logins, scheduling, etc. Here you can find some specific tasks that can be done with SMO.

Below you find an example how you can create a table with SMO:

using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;

public class Sample
{
    public void Create(string connectionstring)
    { 
        SqlConnection connection = new SqlConnection(connectionstring);
        Server server = new Server(new ServerConnection(connection));

        Database database = server.Databases["MyDatabase"];

        // Create table, called Customer
        Table table = new Table(database, "Customer");

        // Add 'ID' column which is the primary key
        Column idColumn = new Column(table, "ID");
        idColumn.DataType = DataType.Int;
        idColumn.Identity = true;
        idColumn.IdentitySeed = 1;
        idColumn.IdentityIncrement = 1;

        // Create a primary key index
        Index index = new Index(table, string.Format("PK_{0}", table.Name));
        index.IndexKeyType = IndexKeyType.DriPrimaryKey;
        index.IndexedColumns.Add(new IndexedColumn(index, "ID"));
        table.Indexes.Add(index);                        

        // Add 'Name' column
        Column nameColumn = new Column(table, "Name");
        nameColumn.DataType = DataType.VarChar(50);

        // Add colums to table
        table.Columns.Add(idColumn);
        table.Columns.Add(nameColumn);

        table.Create();
    }
}

Introduction to MyMeta

MyMeta is an open-source API that allows you to get meta-data from your database. MyMeta is part of MyGeneration, a free code generator hosted on Sourceforge. The MyMeta API can be downloaded separately here (filename is called mymeta_installer.exe).

MyMeta supports the following databases. Note that the API is extensible and that you can provide your own plug-ins

  • Advantage
  • Delimited Text
  • Firebird
  • IBM DB2
  • IBM iSeries (AS400)
  • Interbase
  • Microsoft Access
  • Microsoft SQL CE
  • Microsoft SQL Server
  • MySQL
  • MySQL2
  • Oracle
  • Pervasive
  • PostgreSQL
  • PostgreSQL 8+
  • SQLite
  • VistaDB
  • Xsd3b (xml,xsd,uml,er)

Below you find a code snippet that will iterate, for a SQLite database, all tables, columns and indexes.

string connectionstring = @"data source=SQLiteDatabase.DB";

MyMeta.dbRoot myMeta = new MyMeta.dbRoot();
myMeta.Connect(MyMeta.dbDriver.SQLite, connectionstring);

IDatabase db = myMeta.DefaultDatabase;

foreach (MyMeta.ITable table in db.Tables)
{
    Console.WriteLine("{0} ({1})", table.Name, table.Columns.Count);
    Console.WriteLine("tCOLUMNS");

    foreach (MyMeta.IColumn column in table.Columns)
    {
        Console.WriteLine("tt{0} ({1}), Nullable:{2}",
                 column.Name, column.DataTypeName, column.IsNullable);
    }

    Console.WriteLine("tINDEXES");

    foreach (MyMeta.IIndex index in table.Indexes)
    {
        Console.WriteLine("tt{0}, Unique:{1}", index.Name, index.Unique);
    }
}

MyMeta can map database types to specific ADO.NET data types and language types (C#, VB.NET, etc.). MyMeta has a set of XML files (included in the setup) that contains these mappings. Namely the Languages.xml and DbTargets.xml. Below you find a snippet of the two XML files:

Languages.xml
<Languages>
    ...
    <Language From="SQL" To="C#">
        <Type From="bigint" To="long" />
        <Type From="binary" To="object" />
        <Type From="bit" To="bool" />
        <Type From="char" To="string" />
        <Type From="datetime" To="DateTime" />
        <Type From="decimal" To="decimal" />
        <Type From="float" To="double" />
        <Type From="image" To="byte[]" />
        <Type From="int" To="int" />
        <Type From="money" To="decimal" />
        <Type From="nchar" To="string" />
        <Type From="ntext" To="string" />
        <Type From="numeric" To="decimal" />
        <Type From="nvarchar" To="string" />
        <Type From="real" To="float" />
        <Type From="smalldatetime" To="DateTime" />
        <Type From="smallint" To="short" />
        <Type From="smallmoney" To="decimal" />
        <Type From="text" To="string" />
        <Type From="timestamp" To="byte[]" />
        <Type From="tinyint" To="byte" />
        <Type From="uniqueidentifier" To="Guid" />
        <Type From="varbinary" To="byte[]" />
        <Type From="varchar" To="string" />
        <Type From="xml" To="string" />
        <Type From="sql_variant" To="object" />
    </Language>
    ...
    <Language From="SQLITE" To="C# (SQLite v3.x)">
        <Type From="CHAR" To="string" />
        <Type From="DATETIME" To="DateTime" />
        <Type From="DATE" To="DateTime" />
        <Type From="TIMESTAMP" To="DateTime" />
        <Type From="TIME" To="TimeSpan" />
        <Type From="DECIMAL" To="decimal" />
        <Type From="VARCHAR" To="string" />
        <Type From="NVARCHAR" To="string" />
        <Type From="TEXT" To="string" />
        <Type From="INTEGER" To="long" />
        <Type From="INT" To="long" />
        <Type From="FLOAT" To="float" />
        <Type From="BOOLEAN" To="bool" />
        <Type From="CLOB" To="string" />
        <Type From="BLOB" To="byte[]" />
        <Type From="NUMERIC" To="decimal" />
        <Type From="VARYINGCHARACTER" To="string" />
        <Type From="NATIONALVARYINGCHARACTER" To="string" />
    </Language>
    ...
</Languages>
DBTargets.xml
<DbTargets>
    ...
    <DbTarget From="SQL" To="SqlClient">
        <Type From="bigint" To="SqlDbType.BigInt" />
        <Type From="binary" To="SqlDbType.Binary" />
        <Type From="bit" To="SqlDbType.Bit" />
        <Type From="char" To="SqlDbType.Char" />
        <Type From="datetime" To="SqlDbType.DateTime" />
        <Type From="decimal" To="SqlDbType.Decimal" />
        <Type From="float" To="SqlDbType.Float" />
        <Type From="image" To="SqlDbType.Image" />
        <Type From="int" To="SqlDbType.Int" />
        <Type From="money" To="SqlDbType.Money" />
        <Type From="nchar" To="SqlDbType.NChar" />
        <Type From="ntext" To="SqlDbType.NText" />
        <Type From="numeric" To="SqlDbType.Decimal" />
        <Type From="nvarchar" To="SqlDbType.NVarChar" />
        <Type From="real" To="SqlDbType.Real" />
        <Type From="smalldatetime" To="SqlDbType.SmallDateTime" />
        <Type From="smallint" To="SqlDbType.SmallInt" />
        <Type From="smallmoney" To="SqlDbType.SmallMoney" />
        <Type From="text" To="SqlDbType.Text" />
        <Type From="timestamp" To="SqlDbType.Timestamp" />
        <Type From="tinyint" To="SqlDbType.TinyInt" />
        <Type From="uniqueidentifier" To="SqlDbType.UniqueIdentifier" />
        <Type From="varbinary" To="SqlDbType.VarBinary" />
        <Type From="varchar" To="SqlDbType.VarChar" />
        <Type From="xml" To="SqlDbType.Xml" />
        <Type From="sql_variant" To="SqlDbType.Variant" />
    </DbTarget>
    ...
    <DbTarget From="SQLITE" To="SQLite.NET v3.x">
        <Type From="CHAR" To="DbType.String" />
        <Type From="DATETIME" To="DbType.DateTime" />
        <Type From="DATE" To="DbType.DateTime" />
        <Type From="TIMESTAMP" To="DbType.DateTime" />
        <Type From="TIME" To="DbType.Time" />
        <Type From="DECIMAL" To="DbType.Decimal" />
        <Type From="VARCHAR" To="DbType.String" />
        <Type From="NVARCHAR" To="DbType.String" />
        <Type From="TEXT" To="DbType.String" />
        <Type From="INTEGER" To="DbType.Int64" />
        <Type From="INT" To="DbType.Int32" />
        <Type From="FLOAT" To="DbType.Single" />
        <Type From="BOOLEAN" To="DbType.Boolean" />
        <Type From="CLOB" To="DbType.String" />
        <Type From="BLOB" To="DbType.Binary" />
        <Type From="NUMERIC" To="DbType.Decimal" />
        <Type From="VARYINGCHARACTER" To="DbType.String" />
        <Type From="NATIONALVARYINGCHARACTER" To="DbType.String" />
    </DbTarget>
    ...
</DbTargets>

The xml files can be loaded by setting the LanguageMappingFilename and DbTargetMappingFilename. Setting the right target can be done by the properties Language and DbTarget.

string connectionstring = @"data source=SQLiteDatabase.DB";

MyMeta.dbRoot myMeta = new MyMeta.dbRoot();
myMeta.Connect(MyMeta.dbDriver.SQLite, connectionstring);

myMeta.LanguageMappingFileName = @"C:Program FilesMyGenerationsSettingsLanguages.xml";
myMeta.DbTargetMappingFileName = @"C:Program FilesMyGenerationsSettingsDbTargets.xml";

myMeta.Language = "C# (SQLite v3.x)";
myMeta.DbTarget = "SQLite.NET v3.x";

IDatabase db = myMeta.DefaultDatabase;

foreach (MyMeta.ITable table in db.Tables)
{
    Console.WriteLine("{0} ({1})", table.Name, table.Columns.Count);
    Console.WriteLine("tCOLUMNS");

    foreach (MyMeta.IColumn column in table.Columns)
    {
        Console.WriteLine("tt{0} ({1}), DBTargetType:{2}, LanguageType:{3}",
            column.Name, column.DataTypeName, column.DbTargetType, column.LanguageType);
    }
}

The mapped types can be found in the properties DbTargetType and LanguageType on the IColumn interface.

Visual Studio 2008 Released

Jihaaa, Visual Studio 2008 has been released on MSDN. If you want to have a nice overview of the new features in VS2008, take a look at this post from ScottGu.

Take a look at the following downloads available for VS2008