2013-08-29 3 views
1

Возьмем следующий класс:Возможно ли реализовать расширенный оператор для SqlParameter?

Public Class DocumentNumber 
    Private m_DOC_NUMBER As Integer = 0 

    Public Sub New(ByVal DOC_NUMBER As Integer) 
     m_DOC_NUMBER = DOC_NUMBER 
    End Sub 

    Public Sub New(ByVal DEPOT_CODE As String) 
     Dim ParseInput As Integer = 0 
     If Integer.TryParse(DEPOT_CODE, ParseInput) = False Then 
      m_DOC_NUMBER = 0 
     Else 
      m_DOC_NUMBER = ParseInput 
     End If 
    End Sub 

    ''' <summary> 
    ''' Returns the DOC_NUMBER as a zero-padded number, eg: 0000028374 
    ''' </summary> 
    Public Overrides Function ToString() As String 
     Return Right("0000000000" & m_DOC_NUMBER.ToString(), 10) 
    End Function 

    ''' <summary> 
    ''' Returns the DOC_NUMBER as an integer, use .ToString() zero-padded version. 
    ''' </summary> 
    Public Function ToInteger() As Integer 
     Return m_DOC_NUMBER 
    End Function 

    ''' <summary> 
    ''' Ensure that the DOC_NUMBER object has an implicit convert if assigned to an integer/string 
    ''' </summary> 
    Public Shared Widening Operator CType(ByVal d As DocumentNumber) As Integer 
     Return d.ToInteger() 
    End Operator 

    Public Shared Widening Operator CType(ByVal d As DocumentNumber) As String 
     Return d.ToString() 
    End Operator 

End Class 

Этот класс позволяет мне объявить DocId либо из строки или целого:

Dim DocumentID As New DOC_NUMBER("00123") 
Dim DocumentID As New DOC_NUMBER(123) 

И они могут быть retreived в любом формате, позвонив ToInteger() & ToString() :

Dim NewDocumentID as Integer = DocumentID.ToInteger() 
Dim NewDocumentID as String = DocumentID.ToString() 

Обратите внимание, что два Widening Operator - эти также позволяет неявное преобразование означает .ToInteger() и .ToString() может быть опущен при назначении экземпляра этого класса в целое число или строку, например:

Dim NewDocumentID as Integer = DocumentID 
Dim NewDocumentID as String = DocumentID 

До сих пор; это все отлично работает, моя следующая задача заключается в добавлении неявного преобразования при назначении объекту SqlParameter().

Как вы знаете, если назначить объект на новый SqlParameter(), тип данных может быть опущена и SqlParameter() объект будет понять это автоматически - однако, если я пытаюсь это с моим объектом, очевидно, не удается:

m_db_QueryParams.Add(New SqlParameter("@DOC_NUMBER", OrderNumber)) 

Это дает следующее сообщение об ошибке (и это понятно!):

отображения не существует от типа объекта НомерДокумента к известному под управлением поставщиком собственный типа.

Мой вопрос: Можно ли добавить Widening Operator в мой класс, который будет возвращать это .ToString() метод, когда будучи назначен SqlParameter() без указания типа данных поставляется (как это):

m_db_QueryParams.Add(New SqlParameter("@DOC_NUMBER", OrderNumber)) 'Convert as a string for the SqlParameter 

Я отметили этот вопрос, поскольку оба варианта VB & C# в качестве решения на любом языке были бы подходящими.

+1

Как насчет функции 'ToSqlParameter (имяПараметра в виде строки) в качестве SqlParameter', где вы создаете и вернуть новый SqlParameter и excplicitly Сформулируем SqlDataType, а затем вызвать его как' m_db_QueryParams.Add (OrderNumber.ToSqlParameter ("@ DOC_NUMBER «))'? – Corak

+0

Можете также просто вызвать метод '.ToString()', если это так). Все дело в том, чтобы взять на себя ответственность разработчика за выбор правильного метода '.ToX()' (SQL '@DOC_NUMEBER 'param всегда будет требовать строку), не нужно, чтобы разработчик набирал' .ToString() 'каждый раз, когда они используют его в SQL, когда я должен иметь возможность неявно выполнять это преобразование автоматически - надеюсь, что это имеет смысл :) – HeavenCore

ответ

1

Проблема заключается в том, что конструктор SqlParameter принимает параметр Object.

Поскольку все классы наследуются от Object, ваш расширяющий оператор не будет вызываться, когда вы добавите свое значение.

Это потому, что ваше значение с типом DocumentNumber уже относится к типу Object. Не требуется преобразование в String.

Я думаю, вам будет лучше всего создать код.Можно создать метод расширения на SqlParameterCollection как:

Module SqlParameterExtensions 

    <Extension()> 
    Public Sub MyAddWithValue(coll As SqlParameterCollection, paramName As String, paramValue As Object) 
    If (TypeOf paramValue Is DocumentNumber) Then 
     coll.AddWithValue(paramName, paramValue.ToString()) 
    Else 
     coll.AddWithValue(paramName, paramValue) 
    End If 
    End Sub 
End Module 

И называют это как

Module Module1 

    Sub Main() 
     Dim com As New SqlCommand 
     Dim docNo As New DocumentNumber 
     com.Parameters.MyAddWithValue("@DOC_NO", docNo) 
    End Sub 

End Module 

или вы могли бы ящик с «заводской» метод SqlParameters;

Public Shared Function CreateParameter(name As String, value As Object) As SqlParameter 
    If (TypeOf value Is DocumentNumber) Then 
     value = value.ToString() 
    End If 

    Return New SqlParameter(name, value) 
End Function 
+0

Хм, пока я не получил образование, я должен согласиться; Я думаю, что то, что я хочу, невозможно по причинам, о которых вы заявляете, я пойду дальше и соглашусь с этим в качестве ответа и просто должен согласиться с тем, что мне нужно будет вызвать .ToString() на моем объекте всякий раз, когда я его передаю к SqlParameter. Еще раз спасибо за ваш вклад. – HeavenCore

+0

Добавил некоторые мысли о шаблонах кода, чтобы просто решить вашу проблему ... – mortb

0

Просто используйте ToString() и передайте параметр как NVarchar в sql. Укажите, например, 20 как datalength. Sql может автоматически преобразовывать строки в целые числа. Пример

SQL:

create table tbl1 (id int, data nvarchar(50)); 
insert into tbl1 (id, data) 
values 
(1, 'foo'), 
(2, 'bar'), 
(3, 'foobar'); 

select * from tbl1 
where id = '02'; -- the literal '02' is a string but it will select id 2 (integer) from the table 

---- RESULT--- 
-------------- 
-- | 2 | bar | 

Надеется, что это помогает!

+0

Cheers для ввода! Как я упоминал в разделе комментариев моего вопроса, моя цель здесь заключается в том, чтобы избежать необходимости того, чтобы разработчик набирал .ToString() каждый раз, когда этот класс передается параметру SQL. Это просто дополнительный шаг, который должен быть автоматизирован - меньше набрав, меньше шансов опечаток и так далее. – HeavenCore

Смежные вопросы