将结构映射到本机数据类型

时间:2017-12-01 15:49:57

标签: vb.net

我有以下结构:

Public Structure NonNullableString


    Public Sub New(Optional value As String = "")

        Me.Value = If(value, "")
    End Sub

    Private m_Value As String
    Public Property Value() As String
        Get
            Return If(m_Value, "")
        End Get
        Private Set(value As String)
            m_Value = value
        End Set
    End Property
    Public Shared Widening Operator CType(value As NonNullableString) As String
        Return value.Value
    End Operator
    Public Shared Widening Operator CType(value As String) As NonNullableString
        Return New NonNullableString(value)
    End Operator



    Overrides Function ToString() As String
        Return Value
    End Function

End Structure

我试图通过将SQLCommand放在参数

中来执行
Dim value = NonNullableString("Test")
Dim parameter = New SqlParameter("String", value)   
Using cmd As New SqlCommand(command) With {.Connection = _sqlConnect, .CommandType = type, .Transaction = _transaction}
    cmd.Parameters.Add(parameter)
    cmd.ExecuteNonQuery()
End Using

这会给我带来以下错误:

  

System.ArgumentException:'从对象类型NonNullableString到已知的托管提供程序本机类型不存在映射。'

现在我知道这是因为NonNullableString不是本机类型,我应该使用Dim parameter = New SqlParameter("String", value.Value)

我的问题是,有没有办法将我的结构实际映射到本机类型,这样我就不必再使用.Value了?

1 个答案:

答案 0 :(得分:5)

这些类型是硬编码的,因此您无法对其进行更改。 查看使用的方法以及在switch - default GetMetaTypeFromValue:{/ 3}}中引发异常的方法:

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));
    }
}