Search code examples
c#databasems-accessenumsoledb

Converting primitive Type to OleDbType Enum


I'm attempting to write a generic function for populating compound keys in a few tables of my database.

Unfortunately, I'm limited to using an OleDbConnection so can't make use of many of the niceties of the SqlConnection (and related) classes.

As part of this effort, I need to be able to convert generic system types (which will always be primitive string, int etc) to their OleDbType enum counterparts.

I've viewed this question which has several suggestions in it: primarily, to use a class map. This approach would work fine however, it strikes me as strange that there would be no pre-built and pre-tested component of the .NET Framework that would do this significantly better than any code I would write would. I also dislike reinventing the wheel. The second approach suggested was to utilise the Parameter.ConvertTypeToDbType method in System.Web namespace (a stupid place to put it IMHO but I digress). This appears to work fine however, it yields a DbType enum rather than an OleDbType which I fear may cause compatibility issues.

My current attempt to utilise this approach looks like this:

OleDbParameter searchValueOne = new OleDbParameter("@searchValueOne", System.Web.UI.WebControls.Parameter.ConvertTypeCodeToDbType(Type.GetTypeCode(typeof(T1))));

So my question would be, is there a similar built in function that provides an OleDbType as opposed to a DbType or is going with a TypeMap simply going to be the best approach?


Solution

  • After reading comments and doing some further research it appears that a TypeMap is indeed the best option available.

    Given that there are many cases where the different DB types map to the same Type (see VarChar and BStr amongst others), there are many different options available and which you take will depend on your database structure.

    That being said, here's the class that I've come up with to perform this mapping, it should be a good starting point for anybody who wishes to try this in the future.

    static class OleDbTypeMap
    {
        private static readonly Dictionary<Type,OleDbType> TypeMap = new Dictionary<Type, OleDbType> {
            {typeof(string), OleDbType.VarChar },
            {typeof(long), OleDbType.BigInt },
            {typeof(byte[]), OleDbType.Binary },
            {typeof(bool), OleDbType.Boolean },
            {typeof(decimal), OleDbType.Decimal },
            {typeof(DateTime), OleDbType.Date },
            {typeof(TimeSpan), OleDbType.DBTime },
            {typeof(double), OleDbType.Double },
            {typeof(Exception),OleDbType.Error },
            {typeof(Guid), OleDbType.Guid },
            {typeof(int), OleDbType.Integer },
            {typeof(float), OleDbType.Single },
            {typeof(short), OleDbType.SmallInt },
            {typeof(sbyte), OleDbType.TinyInt },
            {typeof(ulong), OleDbType.UnsignedBigInt },
            {typeof(uint), OleDbType.UnsignedInt },
            {typeof(ushort), OleDbType.UnsignedSmallInt },
            {typeof(byte), OleDbType.UnsignedTinyInt }
        };
        public static OleDbType GetType(Type type) => TypeMap[type];
    }
    

    This could be modified with a GetType(OleDbType type) overload which accesses a different dictionary containing the inverse of the first to make this bi-directional, however, I don't need this functionality so haven't implemented it myself.

    My OleDbParameter line now looks like this:

    OleDbParameter searchValueOne = new OleDbParameter("@searchValueOne", OleDbTypeMap.GetType(typeof(T1)));
    

    Which is much neater than before.