Страница 2 из 3
Re: Получить текущее подключение с базой
Добавлено: 06 фев 2018, 12:31
t0pdevice
Спасибо.
Сделал так:
Код: Выделить всё
foreach (StiDataSource dataSource in _report.DataSources)
{
dataSource.Disconnect();
}
foreach (StiData dataStore in _report.DataStore)
{
if (dataStore.Data is NpgsqlConnection connection)
connection.Close();
}
Но не особо помогло. Запрос все равно выполняется после этого на базе.
Возможно, нужно выполнять Cancel() для выполняемого запроса (NpgsqlCommand).
Но таких данных я из отчёта не могу найти, где получить.
Re: Получить текущее подключение с базой
Добавлено: 06 фев 2018, 12:34
t0pdevice
Если попробовать отменить запрос через тот же pgAdmin, то на клиенте потом появляется ошибка о том, что передача данных разорвана, потому что Render() у отчёта до сих пор выполнял запрос:
Код: Выделить всё
Npgsql.NpgsqlException (0x80004005): Exception while reading from stream ---> System.IO.EndOfStreamException: Попытка чтения после конца потока.
в Npgsql.ReadBuffer.d__27.MoveNext()
в Npgsql.ReadBuffer.d__27.MoveNext()
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.GetResult()
в Npgsql.NpgsqlConnector.d__155.MoveNext()
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
в System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
в Npgsql.NpgsqlConnector.d__154.MoveNext()
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
в System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
в Npgsql.NpgsqlDataReader.d__32.MoveNext()
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
в Npgsql.NpgsqlDataReader.NextResult()
в Npgsql.NpgsqlCommand.d__71.MoveNext()
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
в System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
в Npgsql.NpgsqlCommand.d__92.MoveNext()
--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---
в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
в System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
в System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
в Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
в System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
в System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
в System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)
в System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)
в Stimulsoft.Report.Dictionary.StiDataAdapterHelper.Fill(StiDictionary dictionary, DbDataAdapter dataAdapter, DataTable dataTable, Boolean schemaOnly) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\Dictionary\StiDataAdapterHelper.cs:строка 67
в Stimulsoft.Report.Dictionary.StiSqlSource.RetrieveData(Boolean schemaOnly) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\Dictionary\DataSources\Sql\StiSqlSource.cs:строка 425
в Stimulsoft.Report.Dictionary.StiSqlAdapterService.ConnectDataSourceToData(StiDictionary dictionary, StiDataSource dataSource, Boolean loadData) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\Dictionary\Adapters\Sql\StiSqlAdapterService.cs:строка 401
в Stimulsoft.Report.Dictionary.StiDataSource.Connect(StiDataCollection datas, Boolean loadData) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\Dictionary\DataSources\StiDataSource.cs:строка 1341
в Stimulsoft.Report.Dictionary.StiDataSourcesCollection.Connect(StiDataCollection datas, Boolean loadData) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\Dictionary\DataSources\StiDataSourcesCollection.cs:строка 343
в Stimulsoft.Report.Dictionary.StiDataSourcesCollection.Connect(Boolean loadData) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\Dictionary\DataSources\StiDataSourcesCollection.cs:строка 322
в Stimulsoft.Report.Dictionary.StiDictionary.Connect(Boolean loadData, List`1 dataSources) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\Dictionary\StiDictionary.cs:строка 1511
в Stimulsoft.Report.Engine.StiRenderProviderV2.ConnectToData(StiReport report) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\Engine\EngineV2\StiRenderProviderV2.cs:строка 716
в Stimulsoft.Report.Engine.StiRenderProviderV2.Render(StiReport report, StiRenderState state) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\Engine\EngineV2\StiRenderProviderV2.cs:строка 410
в Stimulsoft.Report.Engine.StiReportV2Builder.RenderSingleReport(StiReport masterReport, StiRenderState renderState) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\Engine\EngineV2\Builders\StiReportV2Builder.cs:строка 144
в Stimulsoft.Report.StiReport.RenderReport(StiRenderState renderState) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\StiReport.Render.cs:строка 350
в Stimulsoft.Report.StiReport.Render(StiRenderState renderState, StiGuiMode guiMode) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\StiReport.Render.cs:строка 210
в Stimulsoft.Report.StiReport.Render(StiRenderState renderState) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\StiReport.Render.cs:строка 97
в Stimulsoft.Report.StiReport.Render(Boolean showProgress, Int32 fromPage, Int32 toPage) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\StiReport.Render.cs:строка 89
в Stimulsoft.Report.StiReport.Render(Boolean showProgress) в D:\Stimulsoft\Stimulsoft.Reports\Stimulsoft.Report\StiReport.Render.cs:строка 79
в Render_DoWork(Object sender, DoWorkEventArgs e)
Re: Получить текущее подключение с базой
Добавлено: 06 фев 2018, 17:57
t0pdevice
Посмотрел, что у connection, полученного через _report.DataStore в State стоит Closed (то есть оно закрыто) и также ProcessID нет.
Сам DataStore заполняется после того, как происходит вызов Dictionary.Synchronize(), но я отслеживал через дебаг, что после заполнения DataStore, даже после вызова Render, у него все равно State = Closed.
Поэтому и закрытие, что я выше указал никак не помогло, так как соединение уже закрытое.
Получается в DataStore хранится не активное подключение, а лишь его настройки.
Re: Получить текущее подключение с базой
Добавлено: 07 фев 2018, 16:16
Aleksey
Здравствуйте,
Можете сделать простой тестовый проект, который показывает как вы запускаете, рендерите отчеты, и выслать нам для анализа.
Попробуем проанализировать, что и где можно сделать.
Спасибо.
Re: Получить текущее подключение с базой
Добавлено: 08 фев 2018, 17:20
t0pdevice
Во вложении простой проект, который показывает саму суть.
Поменяйте в Get_Report() параметры подключения к PostgreSQL базе через NpgsqlConnectionStringBuilder.
Отчёт берется из конечной директории Report.mrt, его суть проста, там просто эмуляция выполнения через pg_sleep (30 секунд).
1. Запускаем выполнение отчёта. Заходим в pgAdmin 3 - "Инструменты" - "Состояние сервера".
2. Видим, что с ApplicationName - "Stimulsoft" выполняется запрос.
3. В приложении нажимаем "Отмена", что должно закрыть форму, уничтожить отчет и разорвать все соединения с базой и выполняющиеся запросы.
4. Смотрим в "Состоянии сервера" запрос еще выполняется.
5. Выделяем наш запрос и жмём в меню "Завершить процесс".
6. Запрос отменяется, а приложение выдаёт ошибку "Exception while reading from stream".
Re: Получить текущее подключение с базой
Добавлено: 12 фев 2018, 15:28
t0pdevice
Удалось воспроизвести?
Re: Получить текущее подключение с базой
Добавлено: 13 фев 2018, 23:12
Aleksey
Здравствуйте,
Спасибот за пример. Воспроизвести получилось.
К сожалению, не получится так из кода закрыть текущее соединение. В данном случае, при рендеринге отчета вызвается метод dataAdapter.Fill(dataTable);
на котором и происходит данная ошибка, либо ожидание завершения выполнения либо ошибка о закрытом соединение.
В вашем случае, вы можете либо предварительно готовить данные и регестрировать их через RagData() метод. В данном случае, вы можете добавлять необходимые проверки еще до рендеринга отчета.
И втрой вариант, реализовать свои методы отмены или передачи конекшена через свой кастомный адаптер для PostgreSQL
http://admin.stimulsoft.com/downloads/d ... greSQL.zip
https://social.msdn.microsoft.com/Forum ... arpgeneral
Спасибо.
Re: Получить текущее подключение с базой
Добавлено: 14 фев 2018, 09:40
t0pdevice
Спасибо за информацию.
Да, я понимаю из-за чего ошибка. У PostgreSQL при отмене запроса на сервере приходит ошибка:
57014: canceling statement due to user request
По сути можно её обрабатывать в catch (PostgresException) для dataAdapter.Fill.
В вашем случае, вы можете либо предварительно готовить данные и регестрировать их через RagData() метод. В данном случае, вы можете добавлять необходимые проверки еще до рендеринга отчета.
Такой вариант рассматривался, но с точки зрения поддержки он не очень удобен, потому что надо постоянно актуализировать колонки в источнике при изменении каких-то данных с процедуры (новые колонки, к примеру). Когда запрос вшит в отчёт - это сделать проще для специального сотрудника, который имеет доступ, к примеру, только к редактору отчётов, а не к исходникам процедур и программы.
Re: Получить текущее подключение с базой
Добавлено: 16 фев 2018, 15:29
Aleksey
Здравствуйте,
> По сути можно её обрабатывать в catch (PostgresException) для dataAdapter.Fill.
Добавили в список задач, посмотрим что можно там сделать.
Спасибо.
Re: Получить текущее подключение с базой
Добавлено: 10 апр 2018, 12:42
aikidos
Aleksey писал(а):И втрой вариант, реализовать свои методы отмены или передачи конекшена через свой кастомный адаптер для PostgreSQL
Здравствуйте. Подключение к базе я смог получить, но я не могу "поймать" создание команд (IDbCommand). Я пробовал написать классы, унаследованные от StiOracleConnector / StiOracleAdapterService / StiOracleDatabase, и наблюдать за вызовом virtual-методов, но никто из них не занимается заполнением StiDataSource.
Суть проблемы: узнать какие запросы отправляет отчёт.
Заранее благодарен за помощь.
Вот, кстати, реализация получения текущего подключения (через событие DbConnectionBase.StateChange можно отлавливать момент открытия соединения). Вдруг кому-то пригодится.
Код: Выделить всё
public class MyDatabase : StiOracleDatabase
{
protected override string DataAdapterType { get; } = typeof(MyAdapter).FullName;
public MyDatabase()
: this(string.Empty, string.Empty)
{
}
public MyDatabase(string name, string connectionString)
: base(name, connectionString)
{
}
public MyDatabase(string name, string alias, string connectionString)
: base(name, alias, connectionString)
{
}
public MyDatabase(string name, string alias, string connectionString, bool promptUserNameAndpassword)
: base(name, alias, connectionString, promptUserNameAndpassword)
{
}
public MyDatabase(string name, string alias, string connectionString, bool promptUserNameAndpassword, string key)
: base(name, alias, connectionString, promptUserNameAndpassword, key)
{
}
public override StiSqlAdapterService GetDataAdapter() => new MyAdapter();
}
Адаптер:
Код: Выделить всё
public class MyAdapter : StiOracleAdapterService
{
public override void CreateConnectionInDataStore(StiDictionary dictionary, StiSqlDatabase database)
{
base.CreateConnectionInDataStore(dictionary, database);
// Подключения можно получить из DataStore:
var connection = dictionary.DataStore[0].Data as OracleConnection;
}
}
Добавление своей реализации:
Код: Выделить всё
StiReport.Dictionary.Databases.Add(new MyDatabase(name, connectionString));