web-dev-qa-db-ja.com

Dapperでは、このコンテキストでは、列挙可能なパラメーターのシーケンス(配列、リストなど)は許可されていません。

私は次のコードを持っています:

static void Main(string[] args){
        string sql= "SELECT * FROM Posts WHERE 1=1 ";
        SqlParameter[] @params= SetDynamicParameter(ref sql, "Param=Value", "Param2=Value2", "ParamN=ValueN");

        IDbConnection connection = new SqlConnection(connectionString);
        IEnumerable<Posts> en = connection.Query<Posts>(sql,param:@params);

        Console.ReadKey(true);
}
 static SqlParameter[] SetDynamicParameter(ref string sql,params string[] sarr) {
        string condition = string.Empty;
        List<SqlParameter> list = new List<SqlParameter>();
        foreach (var item in sarr)
        {
            condition += " AND "+item.Split('=')[0] + "=@" + item.Split('=')[0];
            list.Add(new SqlParameter("@" + item.Split('=')[0], item.Split('=')[1]));
        }
        sql += condition;
        return list.ToArray() ;
  }

出力エラー:このコンテキストでは、パラメーターの列挙可能なシーケンス(配列、リストなど)は許可されていません。

どうすればよいですか?同等の解決策はありますか?

8
Ko.Y

SqlParameter配列の代わりにDapper.DynamicParametersを使用してみてください。

var parameters = new DynamicParameters();
parameters.Add("@ParameterName", parameterValue);

Query<>の代わりにExecuteNonQueryを使用すると、この例外は発生しなくなります。ただし、OracleでQueryを使用すると、別の問題が発生します。

この問題に対する私の解決策は、中間テーブルを使用することでした。私はOracleを使用していました。 Oracleには、sysスキーマの下にある「dual」と呼ばれる特別なテーブルがあります。このテーブルは私にインスピレーションを与え、ユーザーのスキーマの下に別のテーブルを作成しました。

CREATE TABLE USER_SCHEMA.DUAL2
(
  DUMMY  VARCHAR2(1000 BYTE)
)
NOCOMPRESS 
NOCACHE
NOPARALLEL;

必要に応じて長さを伸ばすことができます。テーブルにいくつかの助成金を与えました。次に、クエリをselectからselectステートメントの挿入に変更しました。

INSERT INTO USER_SCHEMA.DUAL2
   (SELECT ID
      FROM ANOTHER_SCHEMA.SOME_TABLE
     WHERE SOME_FLAG = 'M' AND NO IN :NO)

これは、ADO.NETがExecuteNonQueryから結果を返すことができないためです。デフォルトでは、SELECTクエリを実行しますが、クエリごとに-1を返します。 INSERTクエリを提供して、SELECTをシミュレートしています。これは結果を返します。

var parameters = noSplit.Select(x => new { NO = x, SOME_FLAG = flag }).ToList();

var queryResult = dbConnection.Execute(insertSelectQuery, parameters, transactionIfExists);

if (queryResult != parameters.Count)
{
    throw new Exception("Can not find some no");
}
1
Ahmet Koylu

私はこれがあなたにとってちょっと遅いことを知っています、しかし多分それは他の誰かを助けるかもしれません:)

あなたはこのようにそれを行うことができます:

_public class MySqlDataAccess
{
    string _connectionString = "{your connection string}";

    public async Task<IEnumerable<CustomerDto>> GetListAsync(IList<Guid> customers)
    {
        const string query = @"
            SELECT TOP 100 Id,
                    Name
            FROM Customers
            WHERE Id IN @CustomerIdList
        ";

        using (var c = new SqlConnection(_connectionString))
        {
            return await c.QueryAsync<CustomerDto>(query, new { CustomerIdList = customers.ToArray() });
        }
    }
}
_

_WHERE Id IN @CustomerIdList_を実行してから、配列を直接渡す代わりに、new { CustomerIdList = customers.ToArray() }のように配列から匿名型を渡します。

それが役に立てば幸い!

0
Tveitan