7

次の簡単なクエリで Dapper orm を使用しようとしています。

var sqlString = new StringBuilder();
sqlString.Append("select a.acct AccountNumber,");
sqlString.Append("       b.first_name FirstName,");
sqlString.Append("       b.last_name LastName,");
sqlString.Append("       a.rr RrNumber,");
sqlString.Append("       c.addr1 AddressLine1,");
sqlString.Append("       c.addr2 AddressLine2,");
sqlString.Append("       c.addr3 AddressLine3,");
sqlString.Append("       c.addr4 AddressLine4,");
sqlString.Append("       c.addr5 AddressLine5,");
sqlString.Append("       c.addr6 AddressLine6,");
sqlString.Append("       c.addr7 AddressLine7,");
sqlString.Append("       c.addr8 AddressLine8 ");
sqlString.Append("from (pub.mfclac as a left join pub.mfcl as b on a.client=b.client) ");
sqlString.Append("left join pub.mfclad as c on a.client=c.client ");
sqlString.Append("where a.acct = '@ZYX'");

var connection = new OdbcConnection(_connectionString);

var result = connection.Query(sqlString.ToString(),
    new
    {
        ZYX = accountNumber
    });            

ただし、存在することがわかっているaccountNumberでこれを実行すると、dapperは何も返しません。そのため、引用符を削除して、パラメーターが実際にアカウント番号に置き換えられていることを確認しようとしましたが、サーバーから返されたエラーは、「@ZYX」に関する構文エラーを示しています。つまり、ダッパーはパラメーターを指定された値に置き換えていません。なぜこれが起こっているのですか?そこにある限られたドキュメントから、これは「うまくいく」はずです。


編集1

これを機能させることができませんでした。回避策として、string.format を使用してパラメーターを挿入します。

4

2 に答える 2

18

ここには 2 つの問題があります。まず(質問でこれに注意してください)where a.acct = '@ZYX'、SQLルールでは、パラメーターを使用しません-たまたま@記号を含むリテラル文字列と一致するように見えます。SQL-Server (下記の注を参照) の場合、正しい使用法はwhere a.acct = @ZYX.

でも!使用されているためOdbcConnection、名前付きパラメーターは適用されません。実際に SQL-Server などに接続している場合は、ODBC よりも優れた機能とパフォーマンスを備えた純粋な ADO.NET クライアントを使用することを強くお勧めします。ただし、ODBC が唯一の選択肢である場合、名前付きパラメーターは使用されません。数日前までは、これは大きな問題でしたが、OleDb を使用して Dapper でクエリ パラメーターを渡すに従って、コード (まだ NuGet パッケージではありません) が ODBC をサポートするようになりました。ソースからビルドする (または次のリリースを待つ) 場合は、次を使用できるはずです。

...
where a.acct = ?

あなたのコマンドで、そして:

var result = connection.Query(sqlString.ToString(),
new {
    anythingYouLike = accountNumber
});

名前 ( anythingYouLike) は ODBC では使用されないため、任意の名前にすることができます。より複雑なシナリオでは、たとえば次のようになります。

.Execute(sql, new { id = 123, name = "abc", when = DateTime.Now });

dapper は、匿名型がどのように実装されているかについての知識を使用して、値の元の順序を理解し、正しい順序 ( idnamewhen) でコマンドに追加されるようにします。

最後の観察:

つまり、ダッパーはパラメーターを指定された値に置き換えていません。

Dapperは、パラメーターを指定された値に置き換えることはありません。これは単純に sql をパラメーター化する正しい方法ではありません。通常、パラメーターは個別に送信され、次のことが保証されます。

  • SQL インジェクションのリスクはありません
  • 最大クエリ プランの再利用
  • フォーマットの問題なし

一部の ADO.NET / ODBC プロバイダーは、理論的には置換によって内部的に実装することを選択できることに注意してください。ただし、それは dapper とは別のものです。

于 2013-09-20T07:03:25.277 に答える