Я никогда не находил действительно отличный способ сделать это, но я нашел что-то, что сработало. Я не мог создать подкласс класса 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.
Надеюсь, это поможет кому-то еще.