これが私の問題の詳細です。データベース (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
そのため、insert の場合DAL.SCRFL.GetParamStatement
はフォーマットされた文字列を返しINSERT INTO t1 (f1, f2, f3...) values (?, ?, ?...)
、update、delete、select ステートメントの場合は適切な文字列を返します。すべては反射で行われます。ここには構文エラーはありません。ダイレクト プロバイダー タイプのコマンドを使用して、返された値を手動で実行できます。このDAL.SCRFL.GetProperties
メソッドは、キー=プロパティ (フィールド)、値=フィールド値としてフォーマットされたハッシュテーブルを返します。
ここで、各プロパティのパラメーターを作成し、それをコマンド パラメーターに追加して実行する必要があります。この試みは、私のコードで確認できます (ハッシュ テーブルをループして、プロパティと値のペアごとにパラメーターを作成しています)。ただし、最後に説明で例外が発生しData type mismatch in criteria expression.
ます。type
パラメータオブジェクトなどにプロパティを追加しようとしましたsize
が、すべて失敗しました(コメントしました)。これが問題かもしれないと考えるようparam.Value = k.value
に変更しようとしましたが、私のビジネスクラスからのものであり、意図的に null 値を防止しています。何も機能しませんでした!これがテストです。ビジネスクラスの戻り値param.Value = If(IsDBNull(k.value), DBNull.Value, k.value)
k.value
DAL.SCRFL.GetParamStatement
call: テストは OleDb/Access データベースに対して行われ、ご覧のとおり、Memo フィールドを一重引用符で囲みました。私のリフレクション メソッドは、クラス プロパティの属性 (テーブル フィールド名に設定) を読み取りDAL.SCRFL.GetParamStatement
、挿入、更新、削除、および選択に使用する基本的な SQL ステートメントを作成します。AdapterCommandType
組み込みの列挙型です)。
INSERT INTO Clinics
(ClinicId, ClinicName, Phone, Fax, FederalId, DateContracted, Address, City, State, Zip, Inactive, [Memo], DateEntered, EnteredBy, DateModified, ModifiedBy)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
SQL ステートメント (InvokeSql) を実行するこれに似た別のメソッドがあることに注意してください。ここでは、各プロパティの値の型を徹底的にチェックして、SQL ステートメントでプロパティ = 値のペアを作成します。このInvokeSql
メソッドで完全修飾された sql ステートメントを使用すると、単一の警告なしで機能します (概してcnn As IDbConnection = CreateConnection(), cmd = CreateCommand(_cmdText, cnn), cmd.ExecuteNonQuery()
、_cmdText
は sql ステートメントです。ご覧のとおり、パラメーターはありません!)。これは、ジェネリック IDbCommand でパラメーターを使用するたびに問題が発生することを指摘するために言及しています。私の DataFactory 内では、IDbCommand はプロバイダー固有のコマンド タイプに設定されていますが (私DataFactory.CreateCommand(s, cnn)
は汎用の IDbCommand を返します)。
DAL を開発する前は、上記のすべての手順を手動で行っていましたが、すべてのオブジェクト (コマンド、接続など) はプロバイダー固有の型として明示的に宣言されていました。技術的に言えば、一般的なタイプのオブジェクト (プロバイダー固有ではない) で使用したのとまったく同じシナリオを実行しています。しかし、私はそれを機能させることができません。おそらく、何かが欠けています。