0

このクエリを実行する必要があります。

string query = @"SELECT *
                 FROM   hint 
                 WHERE  addedSessionId IN (x, y, z, ............)";


if (_connSource.State != ConnectionState.Open)
    _connSource.Open();

MySqlCommand cmd = new MySqlCommand(query, _connSource);
MySqlDataReader r = cmd.ExecuteReader();

List<Hint> lstHint = new List<Hint>();
while (r.Read())
{
    Hint h = new Hint(Convert.ToInt32(r[0]), Convert.ToInt32(r[1]), 
                      Convert.ToString(r[2]), Convert.ToInt32(r[3]), 
                      Convert.ToInt32(r[4]));
    h.addedSessionId = (Guid)r[5];

    lstHint.Add(h);
}

r.Close(); //important

x, y, z etc上記のコードで、クエリ自体に値を渡すにはどうすればよいですか? x, y, z etcint または string ではなく、バイト配列です。私のコードでは、それらは .net Guid フィールドですが、バイト配列に変換してバイナリ値として db に保存しています。

以下に示すように、パラメーター化された方法でこれを行うことで、私が望むものを達成できます。

string query = @"SELECT *
                 FROM   hint 
                 WHERE  addedSessionId = @newSessionId";


if (_connSource.State != ConnectionState.Open)
    _connSource.Open();

List<Hint> lstHint = new List<Hint>();
foreach (List<Guid> myGuid in lstGuid)
{
    MySqlCommand cmd = new MySqlCommand(query, _connSource);
    cmd.Parameters.AddWithValue("newSessionId", myGuid.ToByteArray());
    MySqlDataReader r = cmd.ExecuteReader();

    while (r.Read())
    {
        int id = Convert.ToInt32(r[0]);

        if (IsThisEntryAlreadyAdded(id, lstHint))
            continue;

        Hint h = new Hint(id, Convert.ToInt32(r[1]),
                          Convert.ToString(r[2]), Convert.ToInt32(r[3]),
                          Convert.ToInt32(r[4]));
        h.addedSessionId = (Guid)r[5];

        lstHint.Add(h);
    }

    r.Close(); //important
}

2番目のアプローチの問題は、比較的遅いことです。IsThisEntryAlreadyAddedここでは、データベースに対してクエリを何度も実行する必要があるだけでなく、この関数を実行してその特定のエントリがまだ追加されていないかどうかを毎回確認する必要があります。

私の質問は、パラメーター化されていないクエリでオブジェクト (私の場合はバイト配列) を渡す方法です。それが不可能な場合、私の質問は、クエリを高速化する代替手段はありますか?

4

2 に答える 2

1

@Reinuzの答えは私の質問に答えますが、私のシナリオでは苦痛です。句の値が非常に多いIN (場合、最大パケット許容サイズを超える可能性があるため、クエリはまったく実行されません。

だから、これが私が最終的に得たものです。これは、大きなテーブルの場合ははるかに高速です。

string query = @"SELECT * 
                 FROM   hint 
                 WHERE  addedSessionId IN (" + GetStringValuesFromGuidList()  + ")";

void GetStringValuesFromGuidList()
{
    string guids = null;
    for (int i = 0; i < lstGuid.Count; i++)
    {
        guids += "'" + UTF8Encoding.Default.GetString(lstGuid[i].ToByteArray()).Replace("\\", "\\\\").Replace("'", "''") + "'";
        if (i < lstGuid.Count - 1)
            guids += ", ";
    }

    return guids;
}

Guid をその文字列表現に変換し、MySQL が同等の文字列検索を実行できるクエリに渡します。

エントリ数が限られている場合は、パラメーター化されたクエリ (Reinuz の回答) が最適です。非常に大きな値の場合は、文字列検索に進みます

編集:ここUTF8Encodingで使用する必要があるのは、データベースの文字セットがユニコードかどうかなどによって異なります.Default。ほとんどの場合、私は成功しました。さらに、バイナリの文字列表現には予約文字が含まれます。したがって、'またはでエスケープします\

于 2012-04-20T18:55:52.813 に答える
1

これがどのように実行できると私が想像するかのサンプルです(疑似コードだけでテストされていません):

string query = @"SELECT * FROM   hint  WHERE  addedSessionId IN (";
MySqlCommand cmd = new MySqlCommand(query, _connSource);
int i = 0;
foreach (List<Guid> myGuid in lstGuid)
{
    query = string.Format("{0}@param{1}", query, i);
    cmd.Parameters.AddWithValue(string.Format("@param{0}", i), myGuid.ToByteArray());
    i++;
    if(i != lstGuid.Count) query = string.Format("{0},", query);
}
query = string.Format("{0})", query);
cmd.CommandText = query;
//Here you have command with constructed query and params
于 2012-04-17T12:18:17.043 に答える