views:

243

answers:

1

I am writing a stored procedure generator and I need to map CLR types to their SQL Server types.

MSDN lists the type mappings at: http://msdn.microsoft.com/en-us/library/ms131092.aspx but I don't want to use a big switch statement to handle the mappings.

Is there a simple way to retrieve the SQL Server type as a string using whatever process is used by System.Data.SqlTypes?

I'd like a method signature like so:

static string GetSqlType(Type clrType)
{
    ...
    return sqlType;
}

So given the following call:

string sqlType = GetSqlType(1.GetType());

sqlType should contain: "int".

+1  A: 

This is made rather more complex since it depends which version of sql server you are willing to target.

  • With a 2008 target you would probably want instances of DateTime to map to the improved datetime2 rather than datetime.
    • TimeSpan is even worse as your fallback option is using DateTime or varchar.

Here is a guide to how sql server will deal with datatypes in replication scenarios

SQL Server Compact Edition adds further confusion as it doesn't support the varchar(max), varbinary(max) column types (you are limited to explicit ~4K length columns).

At some point you will also need to make a heuristic decision on areas with multiple options.

  • textual information may be varchar(n) or varchar(max).
    • or XML from 2005 onwards
    • or TEXT but that is deprecated
  • decimal will map nicely to numeric for input but is risky on output as numeric has a greater scale
  • should bitmaps be image or varbinary?
    • again image is deprecated but this may annoy people still using it.
  • Unsigned integers
    • uint can be safely put into bigint
    • ulong is rather more problematic
    • bigints will be even more fun.

Given all this going with a nice simple switch statement in a utility function will make life much easier than attempting to rely on some opaque BCL library intended only for type translation rather than textual sql creation.
It also makes it clear via a default throw or default varchar(max) what your 'not yet defined' behaviour will be which will remain under your control.

Returning a simple immutable class from the method of the form:

public sealed class SqlServerTypeDescription
{
    // for sql text construction
    public readonly string SqlServerName;
    // for code construction
    public readonly SqlDbType SqlDbType;
    // for code construction
    public readonly Type ClrType;

    // constructor etc.
}

You may want to add optional precision/size value too though that might be something you choose to leave to the user.

ShuggyCoUk