Custom CLRType to SqlDbType Mapping

Right now I’m working on implementing our own ‘LocalDate’ object because the built in ‘DateTime’  is causing several issues for us – it has a time component, Mongo DB automatically converts it to Utc when you save. All of that prompted us to come up with a custom object ‘LocalDate’.

The first requirement is that it’s recognised and saved correctly by Mongo DB, which was a relatively painless process. Then I had to make it behave similarly to the ‘DateTime’ object – create some explicit cast functions, implement various operators etc. Then followed binary and xml serialisation – so far, easy.

The problem arose when I tried to write a unit test to save it to SQL Db and I immediately got the following exception:
“No mapping exists from object type LocalDate to a known managed provider native type.”

I thought, fair enough, ADO.NET doesn’t know what to do with the type, so I must somehow specify how to convert it to a SqlDbType.

The problem is that the mapping is hardcoded and cannot be changed, unless I come up with some hacky solution.

So, for the time being the users have to call ‘ToSqlDbType()’ before saving it to SQL.

The code below is responsible for the problem. As you can see there is no easy solution to this 😦

 static private MetaType GetMetaTypeFromValue(Type dataType, object value, bool inferLen, bool streamAllowed) {
            switch (Type.GetTypeCode(dataType)) {
                case TypeCode.Empty:     throw ADP.InvalidDataType(TypeCode.Empty);
                case TypeCode.Object:
                    if (dataType == typeof(System.Byte[])) {
                        // mdac 90455 must not default to image if inferLen is false ...
                        //
                        if (!inferLen || ((byte[]) value).Length <= TdsEnums.TYPE_SIZE_LIMIT) {
                            return MetaVarBinary;
                        }
                        else {
                            return MetaImage;
                        }
                    }
                    else if (dataType == typeof(System.Guid)) {
                        return MetaUniqueId;
                    }
                    else if (dataType == typeof(System.Object)) {
                        return MetaVariant;
                    } // check sql types now
                    else if (dataType == typeof(SqlBinary))
                        return MetaVarBinary;
                    else if (dataType == typeof(SqlBoolean))
                        return MetaBit;
                    else if (dataType == typeof(SqlByte))
                        return MetaTinyInt;
                    else if (dataType == typeof(SqlBytes))
                        return MetaVarBinary;
                    else if (dataType == typeof(SqlChars))
                        return  MetaNVarChar; // MDAC 87587
                    else if (dataType == typeof(SqlDateTime))
                        return MetaDateTime;
                    else if (dataType == typeof(SqlDouble))
                        return MetaFloat;
                    else if (dataType == typeof(SqlGuid))
                        return MetaUniqueId;
                    else if (dataType == typeof(SqlInt16))
                        return MetaSmallInt;
                    else if (dataType == typeof(SqlInt32))
                        return MetaInt;
                    else if (dataType == typeof(SqlInt64))
                        return MetaBigInt;
                    else if (dataType == typeof(SqlMoney))
                        return MetaMoney;
                    else if (dataType == typeof(SqlDecimal))
                        return MetaDecimal;
                    else if (dataType == typeof(SqlSingle))
                        return MetaReal;
                    else if (dataType == typeof(SqlXml))
                        return MetaXml;                
                    else if (dataType == typeof(SqlString)) {
                        return ((inferLen && !((SqlString)value).IsNull) ? PromoteStringType(((SqlString)value).Value) : MetaNVarChar); // MDAC 87587
                    }
                    else if (dataType == typeof(IEnumerable<DbDataRecord>) || dataType == typeof(DataTable)) {
                        return MetaTable;
                    } else if (dataType == typeof(TimeSpan)) {
                        return MetaTime;
                    }
                    else if (dataType == typeof(DateTimeOffset)) {
                        return MetaDateTimeOffset;
                    }
                    else { 
                        // UDT ?
                        SqlUdtInfo attribs = SqlUdtInfo.TryGetFromType(dataType);
                        if (attribs != null) {
                            return MetaUdt;
                        }
                        if (streamAllowed) {
                            // Derived from Stream ?
                            if (typeof(Stream).IsAssignableFrom(dataType)) {
                                return MetaVarBinary;
                            }
                            // Derived from TextReader ?
                            if (typeof(TextReader).IsAssignableFrom(dataType)) {
                                return MetaNVarChar;
                            }
                            // Derived from XmlReader ? 
                            if (typeof(System.Xml.XmlReader).IsAssignableFrom(dataType)) {
                                return MetaXml;
                            }
                        }
                    }
                    throw ADP.UnknownDataType(dataType);

                case TypeCode.DBNull:    throw ADP.InvalidDataType(TypeCode.DBNull);
                case TypeCode.Boolean:   return MetaBit;
                case TypeCode.Char:      throw ADP.InvalidDataType(TypeCode.Char);
                case TypeCode.SByte:     throw ADP.InvalidDataType(TypeCode.SByte);
                case TypeCode.Byte:      return MetaTinyInt;
                case TypeCode.Int16:     return MetaSmallInt;
                case TypeCode.UInt16:    throw ADP.InvalidDataType(TypeCode.UInt16);
                case TypeCode.Int32:     return MetaInt;
                case TypeCode.UInt32:    throw ADP.InvalidDataType(TypeCode.UInt32);
                case TypeCode.Int64:     return MetaBigInt;
                case TypeCode.UInt64:    throw ADP.InvalidDataType(TypeCode.UInt64);
                case TypeCode.Single:    return MetaReal;
                case TypeCode.Double:    return MetaFloat;
                case TypeCode.Decimal:   return MetaDecimal;
                case TypeCode.DateTime:  return MetaDateTime;
                case TypeCode.String:    return (inferLen ? PromoteStringType((string)value) : MetaNVarChar);
                default:                 throw ADP.UnknownDataTypeCode(dataType, Type.GetTypeCode(dataType));
            }
        }

Microsoft Introduces New Modular .NET Core Delivered by NuGet, Source on GitHub

DevDays®

Big changes are coming to the .NET platform that affect your development wherever you use .NET. The direction helps you develop applications (Web, Azure, Phone, Desktop. Windows Store, Linux, MacOS, iOs and Android) easier. So if you are going horizontal and targeting more than one variation of Windows, then this is for you.

For developers and architects, it provides keys to a new way to looking at how your code should be written. The new .NET implements the kinds of features we face every day. And the solutions are evolving from vertical solutions where each problem was a subset of some other bigger problem. Rather it becomes a set of contracts, where dependencies are clearly defined, where the contract can be implemented in different ways to meet specific needs.

Migrating the .NET base is no small task. Yet, the Microsoft teams have taken on the challenge to make it easier…

View original post 1,838 more words

Overload Resolution Oops

Didactic Code

Earlier today I was observing the output of some calls to Debug.WriteLine when I decided that one of the messages was a little too verbose. Basically the message included a fully qualified name when just the class name would suffice. I found the line which originally read:

and changed it to:

Upon rerunning the app I saw something that surprised me but really shouldn’t have. The message now read “Document: Storing Pending Events for {0}” instead of “Storing Pending Events for Document.” How could this be?

The issue came down to overload resolution. Debug.WriteLine has five overloads but we’re really only interested in the last two:

The final two overloads serve very different purposes but potentially conflict as I was observing. One of them writes a formatted message (using String.Format behind the scenes) whereas the other writes a message and category. It just so happens that changing the second argument…

View original post 136 more words

C# 6.0 – Using Static

Didactic Code

In this installment of my ongoing series covering likely C# 6 language features I’ll be covering one of the features listed as “Done” on the Language feature implementation status page: using static. The idea behind using static is to allow importing members from static classes thus removing the requirement to qualify every member of an imported class with its owner. For the F#ers reading this, using static brings open module to C#.

Consider a method that writes some text to the console:

In this example, we’ve had to specify the Console class three times. The using static feature we can simply invoke the WriteLine method:

The primary benefit in this contrived example is eliminating redundancy but consider a more practical example which makes use of some of System.Math’s members:

Here we’ve had to qualify both PI and Pow with the Math class. Granted, it only appears twice when calculating the area…

View original post 86 more words

C# 6.0 – nameof Expressions

Yes, this feature should’ve introduced ages ago

Didactic Code

This post covers a pre-release C# 6.0 feature. It’s possible that the final implementation may differ from what’s described here.

I’ve lost track of the number of times I’ve needed to pass along the name of something be it a property, method, or type. Historically we’ve relied on hard-coded strings to convey this information but as we’re all too well aware, relying on strings in such a manner is just asking for future problems. For a prime example, we need look no further than our old friend INotifyPropertyChanged.

Consider the following Circle class which typifies the basic INotifyPropertyChanged implementation pattern:

Although this class is pretty boilerplate, it highlights the problem well. First, we’ve violated the DRY principle by encoding a member name in a string. Next, we’ve introduced fragility by relying on the string always reflecting the property name exactly; should the property name ever change we need to…

View original post 492 more words

Evolution of .NET framework

Purnendu Chakrabortty

Microsoft is lauding a new technology, but is .NET really new? The underlying technologies of .NET have been with us for some time. This article explores the maturation of the technologies in and behind .NET.

The Microsoft .NET initiative is all-encompassing, ever-present, and in certain ways, brand-new—but the underlying technologies have been with us for some time. In this article, I’ll explore the evolutionary process that made .NET possible, from MS-DOS and the iterations of Windows to ActiveX. It’s all come together to culminate in .NET.

C:DOSRun (MS-DOS)
DOS carved its spot in computing history as the innovation that let regular folks use computers. Prior to that, no one user ever operated a computer. It was always operated by a team of users.

When DOS came out in 1981, a couple of companies (most notably, Novell) built software to let teams work on bundles of computers—the first PC-based networks. Other companies built products like Telix, PCBoard and Wildcat, enabling the building of the…

View original post 1,353 more words

2015 Preview : Visual Studio 2015 Preview

LGIT Smart Solutions

Game-changing software development coming up!

visual-studio-2013-logo1

I’m currently running Visual Studio 2012 on my laptop, believe it or not, however I’m very excited to know that the Visual Studio 2015 Preview version is now available for user testing purposes, and will be rolled in early 2015 for general use. Among the usual bells and whistles that come with any newer version of Visual Studio, for the very first time, this newer version of Visual Studio comes with feature list of Mac and Linux targeted environments, which will surely bring a huge smile to developers who would like to build .NET applications for their Linux based environments. This release again also comes hot on the heels of a recent announcement that Microsoft has now open-sourced the .NET Framework. Here is a brief feature list to watch out for in Visual Studio 2015.

View original post 238 more words

C# 6.0 – String Interpolation

Didactic Code

I really debated about whether I should write about C#’s upcoming string interpolation feature yet. On one hand it’s an interesting feature that I’m looking forward to. On the other hand, it has already been announced that the feature is going to change from its implementation in the current preview. With that in mind I decided that it’s interesting enough to go ahead and write about it using the current syntax but highlight how it will change, much like how it has been done in the feature description document.

When I first heard that string interpolation was coming to C# I immediately experienced flashbacks to the very early days of my career when I was working with some Perl scripts. I really hated working with the language but something that always stuck with me and I missed when jumping to other languages was its string interpolation feature.

At a…

View original post 632 more words

Blog at WordPress.com.

Up ↑