Обработка базы данных из веб-сервиса - как повысить производительность? - PullRequest
1 голос
/ 01 августа 2009

Я создал веб-сервис, который вызывается со стороны клиента для хранения данных в базе данных. Эти данные отправляются каждые 200 мс от одного пользователя, и каждый раз, когда данные отправляются, соединение с базой данных открывается и закрывается, что, по моему мнению, плохо для производительности.

Данные хранятся путем вызова метода REST.StoreAcceleration () и SQLWorks.StoreAcceleration () следующим образом:

public Response StoreAcceleration(string strSessionString, string strMeasurementTime, string strAccelerationX, string strAccelerationY, string strAccelerationZ)
    {
        SQLWorks sqlWorks = new SQLWorks();
        Response response = new Response();
        try
        {
            string strTime = strMeasurementTime.Replace("_", " ");
            DateTime measurementTime = DateTime.ParseExact(strTime, "yyyy-MM-dd HH:mm:ss:fff", null);
            double accelerationX = Convert.ToDouble(strAccelerationX.Replace(".", ","));
            double accelerationY = Convert.ToDouble(strAccelerationY.Replace(".", ","));
            double accelerationZ = Convert.ToDouble(strAccelerationZ.Replace(".", ","));

            sqlWorks.StoreAcceleration(strSessionString, measurementTime, accelerationX, accelerationY, accelerationZ);

            response.Successful = true;
            response.Comment = "Stored!";
        }
        catch(Exception ex)
        {
            string sDummy = ex.ToString();
            response.Comment = "an error occured!";
            response.Successful = false;
        }

        return response;
    }

public bool StoreAcceleration(string strStringSession, DateTime receivedTime, double accelerationX, double accelerationY, double accelerationZ)
    {
        bool result = false;
        string select =
            "INSERT INTO acceleration (session_id, measurement_time, acceleration_x, acceleration_y, acceleration_z) VALUES (@sessionID, @measurementTime, @accelerationX, @accelerationY, @accelerationZ)";
        SqlConnection conn = new SqlConnection(connectionString);
        SqlCommand cmd = new SqlCommand(select, conn);
        int sessionID = getSessionID(strStringSession);
        if(sessionID == 0)
            return false;
        updateSessions(sessionID);
        string strRecordTime = receivedTime.ToString("yyyy-MM-dd HH:mm:ss:fff");
        cmd.Parameters.AddWithValue("sessionID", sessionID.ToString());
        cmd.Parameters.AddWithValue("measurementTime", strRecordTime);
        cmd.Parameters.AddWithValue("accelerationX", accelerationX.ToString());
        cmd.Parameters.AddWithValue("accelerationY", accelerationY.ToString());
        cmd.Parameters.AddWithValue("accelerationZ", accelerationZ.ToString());
        try
        {
            conn.Open();
            cmd.ExecuteNonQuery();
            result = true;
        }
        catch(Exception ex)
        {
            string sDummy = ex.ToString();
        }
        finally
        {
            conn.Close();
        }
        return result;
    }

Проблема в том, что SqlConnection открывается и закрывается при каждом вызове метода.

Буду признателен, если кто-нибудь подскажет, как улучшить решение, чтобы предотвратить частое открытие / закрытие соединения с базой данных.

Спасибо!

Ответы [ 2 ]

6 голосов
/ 01 августа 2009

Если у вас настроен пул соединений, ваше соединение с базой данных не будет закрыто. Не берите в голову conn.Close(). Из MSDN:

Метод Close откатывает любой ожидающие транзакции. Затем он выпускает соединение с пулом соединений, или закрывает соединение, если соединение пул отключен.

Смотрите здесь, чтобы настроить его, если вы его еще не используете: Пул соединений с SQL Server (ADO.NET) и строки соединений .

Как правило, если в строке подключения нет pooling=false или чего-то подобного, оно уже должно быть активным. Тем не менее, вы можете установить MinPoolSize, чтобы всегда иметь пару готовых к использованию соединений.


Кстати, вы храните полученное время как фактические строки? В противном случае вы можете избавиться от всего этого ToString(..). ADO.NET позаботится о том, чтобы дата не была неверно интерпретирована То же самое относится и к другим ценностям; почему вы конвертируете их в строки?

Наконец, SqlCommand реализует IDisposable, так что вы должны утилизировать его, так же, как соединение. Я бы предложил переписать что-то вроде этого:

public bool StoreAcceleration(string strStringSession, DateTime receivedTime, double accelerationX, double accelerationY, double accelerationZ)
{
    string select =
        "INSERT INTO acceleration (session_id, measurement_time, acceleration_x, acceleration_y, acceleration_z) VALUES (@sessionID, @measurementTime, @accelerationX, @accelerationY, @accelerationZ)";

    int sessionID = getSessionID(strStringSession);
    if (sessionID == 0)
        return false;
    updateSessions(sessionID);

    using (SqlConnection conn = new SqlConnection(connectionString))
    using (SqlCommand cmd = new SqlCommand(select, conn))
    {
        cmd.Parameters.AddWithValue("sessionID", sessionID);
        cmd.Parameters.AddWithValue("measurementTime", receivedTime);
        cmd.Parameters.AddWithValue("accelerationX", accelerationX);
        cmd.Parameters.AddWithValue("accelerationY", accelerationY);
        cmd.Parameters.AddWithValue("accelerationZ", accelerationZ);

        try
        {
            conn.Open();
            cmd.ExecuteNonQuery();
            return true;
        }
        catch (Exception ex)
        {
            return false;
        }
    }
}

Вам больше не нужен вызов Close() в блоке finally. Блок using будет неявно вызывать Dispose(), когда переменная conn выйдет из области видимости. Это, в свою очередь, вызовет метод Close() внутри.

0 голосов
/ 01 августа 2009

По умолчанию пул соединений включен, поэтому повторное открытие соединения с базой данных не так дорого, как мы думали. Совершенно нормально открывать и закрывать соединение для каждого запроса веб-службы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...