Wanted a generic way to pass a DataTable as a parameter to SqlCommand as a TVP (Table Value Parameter). It automatically creates the, IMHO, superfluous User-Defined Table Types. Here's what I have so far:
<Runtime.CompilerServices.Extension()> _
Sub AddTableParameter(ByVal cmd As SqlCommand, ByVal n As String, ByVal dt As DataTable)
Static typeXlat As Dictionary(Of System.Type, SqlDbType)
If typeXlat Is Nothing Then
typeXlat = New Dictionary(Of System.Type, SqlDbType)
typeXlat.Add(GetType(Int64), SqlDbType.BigInt)
typeXlat.Add(GetType(Int32), SqlDbType.Int)
typeXlat.Add(GetType(Int16), SqlDbType.SmallInt)
typeXlat.Add(GetType(Byte), SqlDbType.TinyInt)
typeXlat.Add(GetType(SByte), SqlDbType.TinyInt)
typeXlat.Add(GetType(Boolean), SqlDbType.Bit)
typeXlat.Add(GetType(String), SqlDbType.VarChar)
typeXlat.Add(GetType(Byte()), SqlDbType.VarBinary)
typeXlat.Add(GetType(DateTime), SqlDbType.DateTime)
typeXlat.Add(GetType(DateTimeOffset), SqlDbType.DateTimeOffset)
typeXlat.Add(GetType(Char), SqlDbType.Char)
typeXlat.Add(GetType(Single), SqlDbType.Real)
typeXlat.Add(GetType(Double), SqlDbType.Float)
typeXlat.Add(GetType(Decimal), SqlDbType.Decimal)
typeXlat.Add(GetType(Guid), SqlDbType.UniqueIdentifier)
typeXlat.Add(GetType(Xml.XmlDocument), SqlDbType.Xml)
End If
'assembly the typename and spec
Dim tabletypedef As New List(Of String)
Dim parm As New SqlParameter(n, SqlDbType.Structured)
parm.Value = dt
For Each c As DataColumn In dt.Columns
Dim s As SqlDbType = SqlDbType.Variant
If typeXlat.ContainsKey(c.DataType) Then s = typeXlat(c.DataType)
tabletypedef.Add(c.ColumnName + " " + s.ToString)
Next
Dim tabledef = String.Join(",", tabletypedef.ToArray)
Dim typename = "autotype_" + tabledef
parm.TypeName = "[" + typename + "]"
'create the type if needed
Using cmd2 = New SqlCommand("select count(*) from sys.types where is_table_type=1 and name='" + typename + "'", cmd.Connection)
If cmd2.ExecuteScalar() = 0 Then
cmd2.CommandText = "create type [" + typename + "] as table(" + tabledef + ")"
cmd2.ExecuteNonQuery()
End If
End Using
'add the parm referencing the typename
cmd.Parameters.Add(parm)
End Sub