Как добавить параметры и выполнить универсальный IDbCommand
Вот моя проблема в деталях. Я создал класс слоя доступа к данным, который позволяет мне создавать большинство объектов, необходимых для взаимодействия с базами данных (Odbc, OleDb и SqlClient). Я также создал класс слоя обработки бизнес-объектов с интенсивным использованием Reflection для обработки множества задач с моими бизнес-объектами. Среди прочего, этот класс генерирует каждое отдельное свойство / объект, который мне нужен для обработки DAL (поток SQL, список значений, свойства, набор извлекаемых значений и т. Д.). Посмотрите код ниже для дальнейшего объяснения:
Public Shared Function InvokeParam(Of T)(_classObject As T, _commandType As AdapterCommandType, _arguments As Object()) As Boolean
Dim s As String = DAL.SCRFL.GetParamStatement(_classObject, _commandType, _arguments)
'Debug.Print(s)
Dim hT As Hashtable = DAL.SCRFL.GetProperties(_classObject)
Using cnn As IDbConnection = DataFactory.CreateConnection()
Dim cmd As IDbCommand = DataFactory.CreateCommand(s, cnn)
'cmd.CommandType = CommandType.Text
cmd.CommandText = s
For Each k In hT
Dim param As IDbDataParameter = cmd.CreateParameter()
'param.DbType = DataFactory.ConvertToDbType(k.value.GetType)
param.Value = k.value
param.ParameterName = k.key
'param.Direction = ParameterDirection.Input
'Debug.Print("value:={0}, name:={1}", TypeName(k.value), TypeName(k.key))
Debug.Print("typeMatch:={0}, value:={1}, name:={2}", TypeName(param.Value) = TypeName(k.value), param.Value, param.ParameterName)
cmd.Parameters.Add(param)
Next
If (cmd.ExecuteNonQuery > 0) Then
Return True
End If
End Using
Return False
End Function
Так, DAL.SCRFL.GetParamStatement
возвращает строку в формате INSERT INTO t1 (f1, f2, f3...) values (?, ?, ?...)
для вставки и соответствующих строк для обновления, удаления, выбора операторов. Все сделано с отражением. Здесь нет синтаксической ошибки. Я могу вручную выполнить возвращаемые значения с помощью прямых команд типа провайдера. DAL.SCRFL.GetProperties
Метод возвращает хеш-таблицу, отформатированную как ключ = свойство (поле), значение = значение поля.
Теперь мне нужно создать параметры для каждого свойства и добавить его в параметры моей команды, а затем выполнить его. Эту попытку вы увидите в моем коде (я создаю параметры для каждой пары свойства / значения, зацикливая хеш-таблицу). Однако в конце я получаю исключение с Data type mismatch in criteria expression.
описание. Я пытался добавить type
свойство параметра объекта, size
и т.д. все было неудачно (я их прокомментировал). Я пытался изменить param.Value = k.value
в param.Value = If(IsDBNull(k.value), DBNull.Value, k.value)
думая, что это может быть проблемой, хотя k.value
это из моего бизнес-класса, и я намеренно предотвращаю нулевые значения. Ничего не получалось! вот тест; бизнес-класс вернул значение из DAL.SCRFL.GetParamStatement
call: тест сделан для базы данных OleDb/Access, и, как вы можете видеть, я заключил поле Memo в одинарные кавычки. Мои методы отражения читают атрибуты свойств класса (которые я устанавливаю как имена полей таблицы) и DAL.SCRFL.GetParamStatement
создает базовые операторы SQL для вставки, обновления, удаления и выбора использования. AdapterCommandType
это встроенный тип enum для него).
INSERT INTO Clinics
(ClinicId, ClinicName, Phone, Fax, FederalId, DateContracted, Address, City, State, Zip, Inactive, [Memo], DateEntered, EnteredBy, DateModified, ModifiedBy)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Обратите внимание, что у меня есть другой метод, похожий на этот, который выполняет оператор SQL (InvokeSql), где я тщательно проверяю типы значений для каждого свойства, чтобы создать пары свойство = значение в моем операторе SQL. Используя полностью квалифицированную инструкцию SQL в этом, InvokeSql
, метод работает без одного предупреждения (Rouphly: cnn As IDbConnection = CreateConnection(), cmd = CreateCommand(_cmdText, cnn), cmd.ExecuteNonQuery()
где _cmdText
это заявление SQL Нет параметров, как вы можете видеть!). Я упоминаю об этом, чтобы указать, что проблема возникает всякий раз, когда я использую параметры с общими IDbCommands. Несмотря на то, что внутри моей DataFactory IDbCommand установлен для конкретного типа команды поставщика (мой DataFactory.CreateCommand(s, cnn)
возвращает универсальный IDbCommand).
До разработки DAL я выполнял все вышеперечисленные шаги вручную, хотя все объекты (команды, соединения и т. Д.) Были явно объявлены как типы, специфичные для провайдера. Говоря технически, я использую те же сценарии, что и при работе с объектами общего типа (не зависящими от поставщика). Но я не могу заставить это работать, где-то, возможно, я что-то упускаю.
1 ответ
Я разместил этот вопрос на codeproject, и ответ там. http://www.codeproject.com/Questions/446516/How-to-add-parameters-and-execute-a-generic-IDbCom