More than 1000 downloads for WSCF.blue V1

by Alex Meyer-Gleaves 5 January 2010 - 12:41 AM

On the last day of September in 2009 we released the first version of WSCF.blue on CodePlex. I was very pleased to see that there has now been more than 1000 downloads of the V1 release. Congratulations to the team and thank you to everyone who has downloaded WSCF.blue. It is great to see that interest in contract-fist development is still alive and well. Of course, Christian and Buddhike did a great job of spreading the word with their excellent MSDN article.

image

Now that everyone is back from holidays and feeling refreshed there is no doubt work will continue on the next version. We all have plenty of ideas for the features we would like to see, but what we would really like is feedback from the community on what you want. If you have ideas on what you would like to see in future versions of WSCF.blue please jump onto the forum and let us know.

Tags:

Categories: WSCF | Web Services | Development Tools

Registering open generic types in Autofac 1.4

by Alex Meyer-Gleaves 3 January 2010 - 12:34 AM

UPDATE (5 January 2010): This feature has now been added to the Autofac 1.4 codebase. I had intended to get this one directly into the codebase but Nick and I got our wires crossed, and I ended up posting it as an extension instead. Regardless, this post remains a valid example of extending Autofac 1.4. The RegisterClosedTypesOf method will appear on the ContainerBuilder in the next 1.4 maintenance release. Until then you can use the extension below to register your open generic types.

This is a follow up to my recent post about writing an extension for registering open generic interface types in Autofac 2. The feature described in the first post, along with support for open generic classes, has since been added to the Autofac 2 codebase. You can grab the current 2.1 preview release on the download page and test it out.

I personally feel that the latest preview version of Autofac 2 is stable enough to start using, but I know that even when released not everyone will be able to adopt the new version as soon as they would like. For that reason I have decided to write a similar extension for Autofac 1.4 that supports both open generic interfaces and classes.

Before I move onto the code I would like to draw a distinction between this feature and the RegisterGeneric method found on instances of the the ContainerBuilder class in Autofac 1.4. The RegisterGeneric method allows you to register an open generic type and have a closed generic type created for you when requested. For example, registering List<> and then resolving List<string> will cause Autofac to create a new List<string> instance for you. The difference is that the RegisterGeneric feature does not locate existing types that close the open generic type being registered.

In the unit test below we are ensuring that a closing type is provided for an open generic interface. It is similar to that from the original post, except the extension method is called RegisterClosedTypesOf and extends ContainerBuilder instances instead of RegistrationBuilder instances. The extension method also has a parameter for the assembly that will be scanned to find the closing types. This is different from the Autofac 2 implementation were the assembly is provided to the RegisterAssemblyTypes method, and the containing types are filtered using a delegate provided to the RegistrationBuilder.

[Test]
public void RegisterClosedTypesOf_OpenGenericInterfaceTypeProvided_ClosingGenericTypesRegistered()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assembly assembly = typeof(ICommand<>).Assembly;
    builder.RegisterClosedTypesOf(typeof(ICommand<>), assembly);
    IContainer container = builder.Build();

    Assert.That(container.Resolve<ICommand<SaveCommandData>>(), Is.InstanceOf<SaveCommand>());
    Assert.That(container.Resolve<ICommand<DeleteCommandData>>(), Is.InstanceOf<DeleteCommand>());
}

In addition to the types I used for unit testing in the previous post, there are two new types used for the testing of open generic classes.

/// <summary>
/// An abstract open generic base class.
/// </summary>
public abstract class Message<T>
{
}

/// <summary>
/// A class that closed the open generic type.
/// </summary>
public class StringMessage : Message<string>
{
}

The new message types are used in the next unit test to make sure that support for open generic classes is working.

[Test]
public void RegisterClosedTypesOf_OpenGenericAbstractClassTypeProvided_ClosingGenericTypesRegistered()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assembly assembly = typeof(Message<>).Assembly;
    builder.RegisterClosedTypesOf(typeof(Message<>), assembly);
    IContainer container = builder.Build();

    Assert.That(container.Resolve<Message<string>>(), Is.InstanceOf<StringMessage>());
}

Now that we know how the extension method is used we can move onto the implementation.

/// <summary>
/// Extension methods for the <see cref="ContainerBuilder"/> class.
/// </summary>
public static class ContainerBuilderExtensions
{
    /// <summary>
    /// Scans the types in an assembly and registers those that support any base or interface that closes the 
    /// provided open generic service type.
    /// </summary>
    /// <param name="builder">The container builder being extended.</param>
    /// <param name="openGenericServiceType">The open generic interface or base class type for which implementations will be found.</param>
    /// <param name="assembly">The assembly to scan for the matching types.</param>
    public static void RegisterClosedTypesOf(this ContainerBuilder builder, Type openGenericServiceType, Assembly assembly)
    {
        if (openGenericServiceType == null) throw new ArgumentNullException("openGenericServiceType");

        if (!(openGenericServiceType.IsGenericTypeDefinition || openGenericServiceType.ContainsGenericParameters))
        {
            throw new ArgumentException(
                string.Format("The type '{0}' is not an open generic class or interface type.",
                              openGenericServiceType.FullName));
        }

        foreach (Type candidateType in assembly.GetTypes())
        {
            Type closedServiceType;
            if (findAssignableTypeThatCloses(candidateType, openGenericServiceType, out closedServiceType))
            {
                builder.Register(candidateType).As(closedServiceType);
            }
        }
    }

    /// <summary>
    /// Looks for an interface on the candidate type that closes the provided open generic interface type.
    /// </summary>
    /// <param name="candidateType">The type that is being checked for the interface.</param>
    /// <param name="openGenericServiceType">The open generic service type to locate.</param>
    /// <param name="closedServiceType">The type of the closed service if found.</param>
    /// <returns>True if a closed implementation was found; otherwise false.</returns>
    private static bool findAssignableTypeThatCloses(Type candidateType, Type openGenericServiceType, out Type closedServiceType)
    {
        closedServiceType = null;

        if (candidateType.IsAbstract) return false;

        foreach (Type interfaceType in getTypesAssignableFrom(candidateType))
        {
            if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == openGenericServiceType)
            {
                closedServiceType = interfaceType;
                return true;
            }
        }

        return false;
    }

    /// <summary>
    /// Returns the interface and base types that given a type is assignable from.
    /// </summary>
    /// <param name="candidateType">The type to find assignable types for.</param>
    /// <returns>A list of the assignable interface and base types.</returns>
    private static IEnumerable<Type> getTypesAssignableFrom(Type candidateType)
    {
        foreach (Type interfaceType in candidateType.GetInterfaces())
        {
            yield return interfaceType;
        }

        Type nextType = candidateType;
        while (nextType != typeof(object))
        {
            yield return nextType;
            nextType = nextType.BaseType;
        }
    }
}

After the usual sort of argument checking the types in the assembly are enumerated and tested to see if they close the open generic type. The findAssignableTypeThatCloses method does the work of locating a possible match and returns a value indicating if a match was found. When a match is found the out parameter is assigned the closing type that was located, and the registration is added to the ContainerBuilder. The getTypesAssignableFrom method helps out by returning all the interface and base types assignable from the type it is provided.

That is all that is needed to add support for open generic types in Autofac 1.4.

ContainerBuilderExtensions.cs (3.71 kb)

ContainerBuilderExtensionsTests.cs (3.93 kb)

Tags:

Categories: Garage Sale Code | Microsoft .NET

ReSharper 5.0 Beta available

by Alex Meyer-Gleaves 23 December 2009 - 12:24 PM

JetBrains has provided developers with an early Christmas present releasing the ReSharper 5.0 Beta on Christmas Eve. It looks there are plenty of new features to take for a test drive.

ReSharper 5.0 Beta introduces a great web development feature set; code analysis extended with call tracking, value tracking, and foreach-to-LINQ transformations; project-level refactorings; and a lot more enjoyable features.

The Beta version will work with both Visual Studio 2010 and Visual Studio 2008, although according to this post from JetBrains there are a number of known issues causing problems with support for Visual Studio 2010 Beta 2.

However, keep in mind that Visual Studio 2010 Beta 2 has a number of known issues that in certain scenarios prevent ReSharper from working well. Don’t worry too much though: it doesn’t mean your Visual Studio crashes every time you press Alt+Enter! JetBrains and Microsoft engineers are aware of the problems and working together to solve them by the time Visual Studio 2010 goes RTM.

Head on over to the What's New in ReSharper 5.0 Beta page for a download link and more information on the new features.

Tags:

Categories: Development Tools

Is64BitOperatingSystem and Is64BitProcess in .NET 4.0

by Alex Meyer-Gleaves 21 December 2009 - 12:07 AM

The Environment class in .NET 4.0 contains two new static properties for checking bitness: Is64BitOperatingSystem and Is64BitProcess. In the past I have had to answer these questions in code and wondered how the new properties ended up being implemented. It turns out that the code is actually quite elegant and simple to follow. They have taken advantage of the fact that there are two versions of the mscorlib.dll assembly: one for the x86 version of the framework and another for the x64 version.

The code in the 64-bit version of mscorlib.dll is really simple. If the 64-bit version is loaded, you must be running in a 64-bit process. And if your running in a 64-bit process, you must be running on a 64-bit version of Windows.

public static bool Is64BitOperatingSystem
{
    [SecuritySafeCritical]
    get
    {
        return true;
    }
}

public static bool Is64BitProcess
{
    get
    {
        return true;
    }
}

The code in the 32-bit version of mscorlib.dll is almost as simple. If the 32-bit version is loaded, you must be running in a 32-bit process. In this case though it does not automatically mean you are running on a 32-bit version of Windows. It is possible that the process is running under the WOW64 (Windows-on-Windows 64-bit) subsystem on a 64-bit version of Windows.

The IsWow64Process function is used to determine if the process is running under WOW64. When this returns true you must be running on a 64-bit version of Windows because your process is running under the WOW64 subsystem. It is worth noting that the IsWow64Process function in kernel32.dll is present in current 32-bit versions of Windows but you need to check for its existence to maintain compatibility with versions where it is not present.

public static bool Is64BitOperatingSystem
{
    [SecuritySafeCritical]
    get
    {
        bool flag;
        return ((Win32Native.DoesWin32MethodExist("kernel32.dll", "IsWow64Process") 
            && Win32Native.IsWow64Process(Win32Native.GetCurrentProcess(), out flag)) && flag);
    }
}

public static bool Is64BitProcess
{
    get
    {
        return false;
    }
}

I really like the implementation; it is easy to follow and reliable. You will no longer need for check the IntPtr.Size value that gets hardcoded into mscorlib.dll to determine the bitness of your process, and you wont have to write your own platform invoke code to check the bitness of the operating system either. What joy a couple of simple static properties can bring!

Tags:

Categories: Microsoft .NET

Registering open generic interface types in Autofac

by Alex Meyer-Gleaves 19 December 2009 - 7:22 PM

UPDATE (22 December 2009): I have submitted a patch to Nick and this feature has now been added to the Autofac V2 codebase. While including the patch Nick added support for open generic classes and renamed the extension method to AsClosedTypesOf. This post will be left in its current form and remains a valid example of extending Autofac.

There has been some discussion lately around connecting an open generic type to its implementation types in a number of different dependency injection containers including StructureMap and Unity:

It looks like this is not the first time this scenario has been discussed:

I also recently noticed a posting on the Autofac Google Group asking if it was possible for Autofac to automatically register an open generic interface type against its implementations. Nicholas Blumhardt (the creator of Autofac and all round nice guy) suggested that this would be easy to implement using the new RegisterAssemblyTypes method found on the ContainerBuilder in the upcoming V2 release. Since I have been meaning to take a closer look at the preview of Autofac V2, I decided that having a look into solving this would be a good way for me to dip my toes into the water. I decided to limit the scope to supporting only automatic registrations for open generic interface types. There is no doubt you could use the extensibility provided by the RegisterAssemblyTypes method to take things much further and add features like those supported in the Unity Auto Registration library.

Time to introduce some types that will be used in the unit tests. First is the open generic interface type.

/// <summary>
/// An open generic interface type.
/// </summary>
public interface ICommand<T>
{
    void Execute(T data);
}

Next we have a couple of simple types that will be used as the generic type parameters.

/// <summary>
/// A type to use as a generic parameter.
/// </summary>
public class SaveCommandData
{
}

/// <summary>
/// A type to use as a generic parameter.
/// </summary>
public class DeleteCommandData
{
}

To keep things interesting I decided to include an abstract base class that implements the ICommand interface.

/// <summary>
/// An abstract base class that implements the open generic 
/// interface type.
/// </summary>
public abstract class CommandBase<T> : ICommand<T>
{
    public abstract void Execute(T data);
}

There will be two command implementations. The first will directly implement the ICommand interface.

/// <summary>
/// A command class that directly implements the open 
/// generic interface type.
/// </summary>
public class SaveCommand : ICommand<SaveCommandData>
{
    public void Execute(SaveCommandData data)
    {
    }
}

The second will implement the ICommand interface by inheriting from the CommandBase<T> abstract class.

/// <summary>
/// A command class that implements the open generic interface 
/// type by inheriting from the abstract base class.
/// </summary>
public class DeleteCommand : CommandBase<DeleteCommandData>
{
    public override void Execute(DeleteCommandData data)
    {
    }
}

I will use the first unit test to define the name and signature of the extension method that be will added to the RegistrationBuilder. The extension method will be named WhereTypeClosesOpenGenericInterface and will be available on the RegistrationBuilder returned from the RegisterAssemblyTypes method. It will take a single parameter for the Type that represents the open generic interface type that automatic registrations will be created for.

This first unit test will actually ensure that passing a null value as the method parameter will result in an ArgumentNullException being thrown.

[Test]
public void WhereTypeClosesOpenGenericInterface_NullTypeProvided_ThrowsException()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assert.Throws<ArgumentNullException>(() => builder.RegisterAssemblyTypes(typeof(ICommand<>).Assembly).
        WhereTypeClosesOpenGenericInterface(null));
}

The next unit test will ensure that passing a non-generic type into the method will result in an ArgumentException being thrown.

[Test]
public void WhereTypeClosesOpenGenericInterface_NonGenericTypeProvided_ThrowsException()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assert.Throws<ArgumentException>(() => builder.RegisterAssemblyTypes(typeof(ICommand<>).Assembly).
        WhereTypeClosesOpenGenericInterface(typeof(SaveCommandData)));
}

Another simple unit test will ensure that passing in a closed generic type will also result in an ArgumentException being thrown.

[Test]
public void WhereTypeClosesOpenGenericInterface_ClosedGenericTypeProvided_ThrowsException()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assert.Throws<ArgumentException>(() => builder.RegisterAssemblyTypes(typeof(ICommand<>).Assembly).
        WhereTypeClosesOpenGenericInterface(typeof(ICommand<SaveCommandData>)));
}

The last of the boring unit tests ensures that passing in an open generic type that is not an interface will again result in an ArgumentException being thrown.

[Test]
public void WhereTypeClosesOpenGenericInterface_NonInterfaceOpenGenericTypeProvided_ThrowsException()
{
    ContainerBuilder builder = new ContainerBuilder();
    Assert.Throws<ArgumentException>(() => builder.RegisterAssemblyTypes(typeof(ICommand<>).Assembly).
        WhereTypeClosesOpenGenericInterface(typeof(List<>)));
}

Now onto the interesting unit test that will ensure our registrations are wired up correctly. We use our new WhereTypeClosesOpenGenericInterface extension method and pass it the ICommand<> open generic interface type. Obviously when we resolve a closed generic interface type we except the returned instance to be the type that implements it. In the case of the SaveCommand the implementation of the interface is direct, and with the DeleteCommand the implementation of the interface is through its inheritance of CommandBase<T>.

[Test]
public void WhereTypeClosesOpenGenericInterface_OpenGenericInterfaceTypeProvided_ClosingGenericTypesRegistered()
{
    ContainerBuilder builder = new ContainerBuilder();
    builder.RegisterAssemblyTypes(typeof(ICommand<>).Assembly)
        .WhereTypeClosesOpenGenericInterface(typeof(ICommand<>));
    IContainer container = builder.Build();

    Assert.That(container.Resolve<ICommand<SaveCommandData>>(), Is.TypeOf<SaveCommand>());
    Assert.That(container.Resolve<ICommand<DeleteCommandData>>(), Is.TypeOf<DeleteCommand>());
}

Finally we arrive at the implementation code. I looked at the StructureMap implementation before writing this to keep an eye out for details that I might have otherwise forgotten. Doing so seemed like a good idea considering their code has already been put through its paces. Take a quick look over the code and I will explain what is going on below.

/// <summary>
/// Extension methods for the <see cref="RegistrationBuilder{TLimit,TActivatorData,TRegistrationStyle}"/> class.
/// </summary>
public static class RegistrationBuilderExtensions
{
    /// <summary>
    /// Specifies that a type from a scanned assembly is registered if it implements an interface
    /// that closes the provided open generic interface type.
    /// </summary>
    /// <typeparam name="TLimit">Registration limit type.</typeparam>
    /// <typeparam name="TRegistrationStyle">Registration style.</typeparam>
    /// <typeparam name="TScanningActivatorData">Activator data type.</typeparam>
    /// <param name="registration">Registration to set service mapping on.</param>
    /// <param name="openGenericInterfaceType">The open generic interface type for which implementations will be found.</param>
    /// <returns>Registration builder allowing the registration to be configured.</returns>
    public static RegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle>
        WhereTypeClosesOpenGenericInterface<TLimit, TScanningActivatorData, TRegistrationStyle>(
            this RegistrationBuilder<TLimit, TScanningActivatorData, TRegistrationStyle> registration, Type openGenericInterfaceType)
        where TScanningActivatorData : ScanningActivatorData
    {
        if (openGenericInterfaceType == null)
        {
            throw new ArgumentNullException("openGenericInterfaceType");
        }

        if (!(openGenericInterfaceType.IsGenericTypeDefinition || openGenericInterfaceType.ContainsGenericParameters) || !openGenericInterfaceType.IsInterface)
        {
            throw new ArgumentException("The type '" + openGenericInterfaceType.FullName + "' is not an open generic interface type.");
        }

        return registration.Where(candidateType => findInterfaceThatCloses(candidateType, openGenericInterfaceType) != null)
            .As(candidateType => findInterfaceThatCloses(candidateType, openGenericInterfaceType));
    }

    /// <summary>
    /// Looks for an interface on the candidate type that closes the provided open generic interface type.
    /// </summary>
    /// <param name="candidateType">The type that is being checked for the interface.</param>
    /// <param name="openGenericInterfaceType">The open generic interface type to locate.</param>
    /// <returns>The type of the interface if found; otherwise, <c>null</c>.</returns>
    private static Type findInterfaceThatCloses(Type candidateType, Type openGenericInterfaceType)
    {
        if (candidateType.IsAbstract) return null;

        foreach (Type interfaceType in candidateType.GetInterfaces())
        {
            if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == openGenericInterfaceType)
            {
                return interfaceType;
            }
        }

        return (candidateType.BaseType == typeof(object)) 
            ? null
            : findInterfaceThatCloses(candidateType.BaseType, openGenericInterfaceType);
    }
}

First the parameter for the open generic interface type is checked to ensure that it is not null and that it is indeed an open generic interface type. Next we use the RegistrationBuilder instance that is being extended to determine what types we want registered and what their service mappings will be. The important methods on the RegistrationBuilder that enable this are the Where and As methods. The Where method takes a predicate that is used to filter the list of scanned types down to only those you are interested in registering. The As method is used to provide the service mappings for the types that got included for registration after the filter was applied.

The Func<Type,bool> predicate provided to the Where method on the RegistrationBuilder instance utilizes a private method named findInterfaceThatCloses. When the findInterfaceThatCloses method is called it will look for an interface on the type provided as the first parameter, that matches the type provided as the second parameter. In our case we are passing in the candidate type that was provided by the assembly scanning process, and the open generic interface type we are interested in matching. When no matching interface is found null is returned. When used in the delegate parameter provided to the Where method for filtering we check for the return from findInterfaceThatCloses being not null, and use the actual type returned from the method for the delegate parameter provided to the As method for mapping the services. We know that when the As method is called it will only be provided with types that were included by the filter, so we need not worry about receiving a type that does not implement the interface at this point.

The implementation of the findInterfaceThatCloses method ensures that only types which are not abstract are checked for matching interfaces. It then iterates through the available interfaces and checks if any match the open generic interface type provided. If no matching interface is found we recursively check if the type’s base class implements the interface until we reach a type that inherits directly from object.

As you can see Nick has done a great job making Autofac extensible, allowing additional requirements for your container to be met with very little effort on your part. I think the next version of Autofac is shaping up nicely and I look forward to posting more about it in the future.

Tags:

Categories: Garage Sale Code | Microsoft .NET

Limiting CTE recursion depth in SQL Server

by Alex Meyer-Gleaves 14 December 2009 - 12:24 AM

I can think of a few different cases that will result in the recursion of a CTE (Common Table Expression) in SQL Server coming to an end:

  • You run out records to recursively select and your result is returned without error.
  • You reach the default maximum recursion depth of 100 and an error occurs.
  • You reach the maximum recursion depth you specified using the MAXRECURSION query hint (a value between 1 and 32767) and an error occurs.
  • You set the maximum recursion depth to have no limit using the MAXRECURSION query hint (a value of 0) and crash your server due to an infinite loop.
  • You reach a maximum recursion depth that you manually control in your query.

Obviously, some of these cases have a more desirable outcome than others. While the MAXRECURSION query hint does provide a mechanism to ensure you do not end up in an infinite loop, reaching the limit it imposes causes an error to occur, and that is something to be avoided. It is also possible to set the MAXRECURSION query hint to 0 which will result in no limit being applied, so without a mechanism of your own in place to limit the recursion depth, you have definitely made it easier to get yourself into trouble.

I prefer to manually restrict the recursion level and set the MAXRECURSION query hint to be the same if my restriction is greater than 100. Remember, 100 is the default limit when the MAXRECURSION query hint is not present, and you must exceed and not just reach the limit for the error to occur.

The query below is manually limited to 50 levels of recursion. There is no need to specify the MAXRECURSION query hint because the default of 100 will never be reached.

WITH LimitedLoop AS
(
    SELECT 0 AS RecursionLevel
        
    UNION ALL
    
    SELECT (LimitedLoop.RecursionLevel + 1) AS RecursionLevel
    FROM LimitedLoop
    WHERE (LimitedLoop.RecursionLevel + 1) <= 50
)
SELECT * FROM LimitedLoop

This query is manually limited to 200 levels of recursion. The MAXRECURSION query hint is specified because its default value of 100 is less than the manually imposed limit.

WITH LimitedLoop AS
(
    SELECT 0 AS RecursionLevel
        
    UNION ALL
    
    SELECT (LimitedLoop.RecursionLevel + 1) AS RecursionLevel
    FROM LimitedLoop
    WHERE (LimitedLoop.RecursionLevel + 1) <= 200
)
SELECT * FROM LimitedLoop
OPTION (MAXRECURSION 200)

It is also worth noting that the first query will return 51 rows and the second 201 rows. This is because the first record returned containing the 0 in the RecursionLevel column is part of the base result set and not the recursive invocation.

Tags:

Categories: Database

Would you become a signatory of the SOA Manifesto?

by Alex Meyer-Gleaves 20 November 2009 - 11:12 PM

Most developers have heard of the Agile Manifesto, but did you know there is also a SOA Manifesto? Like the Agile Manifesto, and perhaps even more so, I am sure it will be wide open to interpretation and will spark some level of debate. There is already a SOA Manifesto Dialog site dedicated to discussion of the manifesto, and a poll that it hosts suggests that opinion is indeed varied. I have embedded the same poll below if you would like to voice your opinion right now.

I am just happy to see some activity taking place within the SOA community, and for SOA to be getting some form of press once again. SOA has provided a great deal of benefit to the many organisations that have embraced it, and I believe that fact should be recognised. If you too believe in the benefits that SOA delivers you should head on over to the site, and if you agree with what is written become a signatory to the manifesto.

Tags:

Categories: Web Services

Free database goodness: LightSpeed Express and SQLite

by Alex Meyer-Gleaves 17 November 2009 - 11:24 PM

I have used VistaDB Express for many hobby projects in the past and found it to be simple and reliable. This blog is running on VistaDB Express and it has never given me any trouble. Unfortunately, with the release of VistaDB 4 there will no longer be a free edition available for any purpose. While this is very disappointing I can understand why they have taken this stance.

Sorry, we had to discontinue the free edition of VistaDB due to the support demands, and the number of companies who were using it for commercial purposes.  We have to put food on the table and feed our families just like anyone else, this was the free as in beer problem (it cost us a lot to build and support, but people used it to make money and not pay us).

When it comes to small hobbyist projects this is not the end of the world, as there are other free products available that will meet such needs. I made the jump over to SQLite, another very popular and free embedded database engine. The main reason I chose to use VistaDB Express over SQLite in the past, was the fact that it had a wider range of supported data types and good management tools provided out of the box. However, there is a free management tool for SQLite called SQLite Database Browser that does a good job, and when used with a decent ORM the reduced number of supported data types in SQLite is soon forgotten.

image I have been using LightSpeed Express from Mindscape as the ORM atop of both database engines, and I must say that I absolutely love it. This free edition is limited to creating a model with at most eight classes, which I have found to be enough when coding for fun. If you don’t need many entities in your model it is well worth using given the features it provides. To see how the LightSpeed feature set stacks up against other ORM technologies including LINQ to SQL and LINQ to Entities have a read of the comparison document on the Mindscape website. LINQ to LightSpeed is the standout feature that makes this framework a winner for me. It enables you to use LINQ against any of the databases that LightSpeed supports: SQL Server, Oracle, PostgreSQL, MySQL, SQLite, VistaDB, Firebird and Amazon SimpleDB.

LightSpeed has an editor for Visual Studio that allows you to build your model in a manner similar to that provided by LINQ to SQL and LINQ to Entities. You can even use the design time tools to create a new database from an existing one. This is exactly what I did when moving an existing project from VistaDB Express to SQLite.

The LightSpeed designer extends that portability to design time. By changing the connection string and data provider on a model, and choosing Update Database, you can rapidly create much of your schema on the new database, rather than having to manually translate the SQL CREATE scripts from one dialect to another.

Once you have a good ORM in place you tend not to worry so much about the underlying database engine, well at least when your requirements are simple and you have no desire to spend money. This was certainly the case for me with VistaDB Express and SQLite. It would be interesting to know how many other VistaDB Express users have switched to a completely different database engine for their home projects despite the low price of the entry level VistaDB 4 Lite version. Regardless, I can assure you that LightSpeed Express will make any database engine you choose easier to work with, and like any good ORM will allow you to more easily change it at a later point in time.

Tags: ,

Categories: Database | Development Tools

OM NOM NOM NOM

by Alex Meyer-Gleaves 4 November 2009 - 6:56 PM

I really like the current Google logo! Check out the Google Logos Collection for other Google logos from around the world.

Cookie Monster Google Logo

Tags:

Categories: Random

Contract-First article on MSDN

by Alex Meyer-Gleaves 4 October 2009 - 12:44 PM

Congratulations to Christian and Buddhike for their excellent MSDN article: Schema-based Development with Windows Communication Foundation. If you are new to contract-first web service development, or even if you have been practicing it for a while, I am sure you will really enjoy reading this article. It is great to see an article on MSDN that is focused on contract-first and how it can be achieved with WCF. Of course, there is a section dedicated to the WSCF.blue Visual Studio 2008 Add-in.

The diagram below was created for the article, and Christian has also put it on the WSCF.blue homepage on CodePlex.

The schema-first approach has five discrete steps.

I really like this diagram, it paints a picture that is very clear and easy to understand. It shows that there is a sequence of steps that are undertaken when doing contract-first development, and highlights that this entire sequence becomes an iterative process. Well done guys!

Tags: ,

Categories: Web Services | WSCF

About the author

Alex Meyer-Gleaves I'm a software developer living in Australia (that island like continent in the southern hemisphere). I love Microsoft .NET and C#. I hate early mornings, slow drivers and Lotus Notes.

Google Reader Clips

SpringWidgets
RSS Reader
This widget is the staple of our platform. Read all your feeds right here with thisone widget - Supported feeds are OPML, RSS, RDF, ATOM. Watch your favorite Podcastin the embedded Video Player on the Desktop or publish your own video playlist toyour site for others to view!

Recent Comments

Comment RSS

Links

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in  anyway.

© Copyright 2008