24.01.2019, 07:36 | #1 |
Участник
|
Call SQL Stored Procedure формирование отчета
Кто нибудь сталкивался с формированием отчетов с помощью хранимой процедуры SQL. Или данный метод противоречить с политикой Axapta. Здесь столкнулся с одной проблемой. У меня запускается данный отчет, а у пользователя выдается ошибка. Вообще стоит работать с подобным методом, вызов хранимой процедуры через SqlClient и формировать отчеты?
X++: #AviFiles //Алгоритм заполнения описывается не в run(), а в fillDocument() protected void fillDocument() { System.Data.SqlClient.SqlConnection cnn; System.Data.SqlClient.SqlCommand cmd; System.Exception e; System.Data.SqlClient.SqlDataReader sdr; System.Data.SqlClient.SqlParameterCollection parameterCollection; SysSQLSystemInfo systemInfo = SysSQLSystemInfo::construct(); CodeAccessPermission perm2 = new InteropPermission(InteropKind::ClrInterop); str sqlStr, beg_date, end_date; SqlSystem sqlSystem; SqlStatementExecutePermission sqlPermission; // System.Data.DataTable stockTable; System.Data.DataRow row; System.Data.DataRowCollection rows; Counter counter; int i; str picName; boolean bPrint; container con, conDim, conValues; ItemId itemId; ItemName itemName; UnitId unitId; str itemType, inventPicName; str dimension5, dimension2, dimension2_; InventSerialId inventSerialId; InventGtdId_RU inventGtdId_RU; WMSLocationId wmsLocationId; LedgerAccount account, accountOffset; TransDate transDate, deliveryDate; CLRObject clrObj; InteropPermission perm; System.Exception ex; boolean found; ; excelWorksheet.range('Company').value2(CompanyInfo::find().Name); excelWorksheet.range('dates').value2(strfmt("%1 - %2", fromDate, toDate)); //Инициация буфера отчета. В него помещаются строки отчета excelWorksheet.bufferStart(); //this.progressInit("Реестр платежей", SysQuery::countTotal(queryRun), #AviTransfer); this.progressInit("Выгрузка в excel", 10000, #AviTransfer); stockTable = this.CreateTable(); rows = stockTable.get_Rows(); sqlStr = "dbo.ALA_InventTransRest"; beg_date = date2Str(fromDate, 321, DateDay::Digits2, DateSeparator::None, DateMonth::Digits2, DateSeparator::None, DateYear::Digits4); end_date = date2Str(toDate, 321, DateDay::Digits2, DateSeparator::None, DateMonth::Digits2, DateSeparator::None, DateYear::Digits4); cnn = new System.Data.SqlClient.SqlConnection( strfmt("Data Source=%1;Initial Catalog=%2;Integrated Security=True;Connection Timeout=120", systemInfo.getLoginServer(), systemInfo.getloginDatabase())); cmd = cnn.CreateCommand(); cmd.set_CommandText(sqlStr); cmd.set_CommandType(System.Data.CommandType::StoredProcedure); parameterCollection = cmd.get_Parameters(); parameterCollection.AddWithValue("@beg_date", beg_date); parameterCollection.AddWithValue("@end_date", end_date); parameterCollection.AddWithValue("@item", item); try { cnn.Open(); sdr = cmd.ExecuteReader(); try { while (sdr.Read()) { counter++; account = sdr.GetString(0); accountOffset = sdr.GetString(1); itemId = sdr.GetString(2); itemName = sdr.GetString(3); unitId = sdr.GetString(4); itemType = sdr.GetString(5); inventLocationId = sdr.GetString(6); wmsLocationId = sdr.GetString(7); inventSerialId = sdr.GetString(8); inventPIC = sdr.GetString(9); inventPicName = sdr.GetString(10); dimension5 = sdr.GetString(11); dimension2_ = sdr.GetString(12); deliveryDate = sdr.GetDateTime(13); dimension2 = sdr.GetString(14); inventGtdId_RU = sdr.GetString(15); sQty = sdr.GetDecimal(16); sAmount = sdr.GetDecimal(17); iQty = sdr.GetDecimal(18); iAmount = sdr.GetDecimal(19); oQty = sdr.GetDecimal(20); oAmount = sdr.GetDecimal(21); eQty = sdr.GetDecimal(22); eAmount = sdr.GetDecimal(23); transDate = sdr.GetDateTime(24); conValues = [counter, account, accountOffset, itemId, itemName, unitId, itemType, inventLocationId, wmsLocationId, inventSerialId, dimension5, dimension2_, deliveryDate, dimension2, inventGtdId_RU, inventPIC, inventPicName, sQty, sAmount, iQty, iAmount, oQty, oAmount, eQty, eAmount, transDate]; excelWorksheet.bufferAddLine(conValues, 'Data_Body', 'Data_Bottom'); if ((counter > 1) && (counter mod 300 == 0)) { i = i > 0 ? 8 + counter - 300 : 8; excelWorksheet.bufferPost(strfmt("A%1", i), connull()); //Инициация буфера отчета. В него помещаются строки отчета excelWorksheet.bufferStart(); } this.parmProgress().incCount(); } sdr.Dispose(); excelWorksheet.bufferPost(strfmt("A%1", 7 + counter - (counter mod 300)), ['Data_Body','Data_Bottom']); } catch (Exception::Error) { info("Caught 'Exception::Error'."); } catch (Exception::CLRError) { perm = new InteropPermission(InteropKind::ClrInterop); if (perm == null) { return; } perm.assert(); e = ClrInterop::getLastException(); if (e != null) { e = e.get_InnerException(); if (e != null) { info(e.ToString()); } } //CodeAccessPermission::revertAssert(); } } catch (Exception::CLRError) { ex = ClrInterop::getLastException(); while(ex) { error(ex.get_Message()); ex = ex.get_InnerException(); } if (sdr != null) sdr.Dispose(); } if (cnn.get_State() == System.Data.ConnectionState::Open) cnn.Close(); CodeAccessPermission::revertAssert(); } |
|
24.01.2019, 13:07 | #2 |
NavAx
|
Ну, как тебе сказать...
Вот ты и наткнулся на первую проблему - юзерам надо раздавать права еще и на SQL. Вторая: код бизнес-логики "размазывается" между сущностями - еще одни проблемы при развертывании и поддержке. Нужна экспертиза по SQL хранимкам и DBA нужен не совсем деревянный. Конечно, это противоречит единому стилю и духу AX. Она ж для того и писана, чтобы вот это вот все выкинуть и взять единую среду. Вопрос баланса и возможностей. Если минусы нивелируются плюсами (обычный плюс - скорость), то почему бы и нет? Вон в соседней теме временные таблицы запилили в 2009. Я бы вот поостерегся такое пилить клиенту, работая в консалтинге. А сидя на самом клиенте - может, и сделал бы, если других путей не очень-то. Еще и плюс можно поиметь в виде незаменимости, ибо разобраться в таком - надо ж не средним специалистом в AX быть...
__________________
Жизнь прекрасна! Если, конечно, правильно подобрать антидепрессанты... Последний раз редактировалось Maximin; 24.01.2019 в 13:09. |
|
|
За это сообщение автора поблагодарили: ax_mct (2). |
24.01.2019, 14:11 | #3 |
Banned
|
В коде бардак с .assert() как минимум для SqlStatementExecutePermission.
То есть имеет смысл убедиться в том что все permisson.assert() вызываются до вызовов. |
|
25.01.2019, 11:36 | #4 |
Участник
|
Если вы работаете прямо на сервере, то обычным пользователям не дана такая роскошь.
Измените свой код, чтобы он вызывался на стороне сервера. Т.е. либо RunOn = Server, либо X++: public server static void ...
__________________
// no comments |
|
|
За это сообщение автора поблагодарили: TalgatAb (1). |
25.01.2019, 12:22 | #5 |
Участник
|
Спасибо за рекомендации, как раз рассматриваю подобный метод:
X++: server static ResultSet executeQuery(str sql, Connection connection = new Connection()) { SqlStatementExecutePermission sqlPerm; Statement statement; ResultSet resultSet; ; sqlPerm = new SqlStatementExecutePermission(sql); sqlPerm.assert(); statement = connection.createStatement(); resultSet = statement.executeQuery(sql); CodeAccessPermission::revertAssert(); return resultSet; } |
|
|
За это сообщение автора поблагодарили: ax_mct (1). |
|
|