Профилирование дозвукового SQL с помощью MvcMiniProfiler - PullRequest
3 голосов
/ 02 марта 2012

Кто-нибудь имел успех в профилировании своих Subsonic SQL-запросов с MvcMiniProfiler? Кажется, я не могу точно найти, где в Subsonic подключиться к процессу создания SqlConnection.

1 Ответ

1 голос
/ 10 апреля 2012

Я никогда не находил действительно отличный способ сделать это, но я нашел что-то, что сработало. Я не мог создать подкласс класса SubSonic.DataProviders.DbDataProvider, так как конструктор был «внутренним» (не удивительным). Поэтому я просто скопировал исходный код в свой проект и внес несколько изменений.

Основная строка кода, которая должна быть изменена, находится в методе «CreateConnection», она должна возвращать ProfiledDbConnection.

public DbConnection CreateConnection(string connectionString)
        {
            DbConnection conn = Factory.CreateConnection();
            conn.ConnectionString = connectionString;
            if(conn.State == ConnectionState.Closed) conn.Open();
            return conn;
        }

Так как соединение больше не является SqlConnection, это вызвало ошибку приведения в некотором существующем коде. Чтобы исправить это, я изменил метод ExecuteDataSet, чтобы использовать соединение из области вместо фабрики.

public DataSet ExecuteDataSet(QueryCommand qry)
{
            if (Log != null)
                Log.WriteLine(qry.CommandSql);
#if DEBUG
            //Console.Error.WriteLine("ExecuteDataSet(QueryCommand): {0}.", qry.CommandSql);
#endif
            using (AutomaticConnectionScope scope = new AutomaticConnectionScope(this))
            {
                DbCommand cmd = scope.Connection.CreateCommand();
                cmd.CommandText = qry.CommandSql;
                cmd.CommandType = qry.CommandType;
                DataSet ds = new DataSet();
                cmd.Connection = scope.Connection;
                AddParams(cmd, qry);
                DbDataAdapter da = Factory.CreateDataAdapter();
                da.SelectCommand = cmd;
                da.Fill(ds);

                return ds;
            }
        }

Я также изменил метод ExecuteScalar, чтобы использовать область соединения.

public object ExecuteScalar(QueryCommand qry)
        {
            if (Log != null)
                Log.WriteLine(qry.CommandSql);

#if DEBUG
            //Console.Error.WriteLine("ExecuteScalar(QueryCommand): {0}.", qry.CommandSql);
            //foreach (var param in qry.Parameters) {
            //    if(param.ParameterValue==null)
            //        Console.Error.WriteLine(param.ParameterName + " = NULL");
            //    else
            //        Console.Error.WriteLine(param.ParameterName + " = " + param.ParameterValue.ToString());
            //}
#endif

            object result;
            using (AutomaticConnectionScope automaticConnectionScope = new AutomaticConnectionScope(this))
            {
                DbCommand cmd = automaticConnectionScope.Connection.CreateCommand();
                cmd.Connection = automaticConnectionScope.Connection;
                cmd.CommandType = qry.CommandType;
                cmd.CommandText = qry.CommandSql;
                AddParams(cmd, qry);
                result = cmd.ExecuteScalar();
            }

            return result;
        }

Кажется, сейчас все работает. В настоящее время я использую IOC, чтобы определить, использует ли сам класс базы данных этот ProfilingDbDataProvider или существующий DbDataProvider. Я изменил это в генерации кода класса Context для извлечения из IOC вместо использования ProviderFactory.

Надеюсь, это поможет кому-то еще.

...