using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Text; using System.Text.RegularExpressions; using Kreta.Framework; using Kreta.Framework.Util; using SDA.DataProvider; namespace Kreta.DataAccessManual.Util { internal static class DataUtil { #region Session public static bool ActivateSession(string sessionId) { if (string.IsNullOrWhiteSpace(sessionId)) return false; if (UserContext.Instance == null || !UserContext.Instance.Activated) { SDAServer.Instance.SessionManager.ActivateSession(sessionId); return true; } return false; } public static void DeactivateSession(string sessionId) { if (UserContext.Instance != null && UserContext.Instance.Activated) { SDAServer.Instance.SessionManager.DeActivateSession(sessionId); } } public static bool ActivateOrganizationSystemSession(string intezmenyAzonosito) { if (string.IsNullOrWhiteSpace(intezmenyAzonosito)) return false; if (UserContext.Instance == null || !UserContext.Instance.Activated) { SDAServer.Instance.SessionManager.ActivateOrganizationSystemSession(intezmenyAzonosito); return true; } return false; } public static void DeactivateOrganizationSystemSession() { if (UserContext.Instance != null && UserContext.Instance.Activated) { SDAServer.Instance.SessionManager.DeactivateOrganizationSystemSession(); } } public static bool ActivateMobileSession(string intezmenyAzonosito) { return ActivateOrganizationSystemSession(intezmenyAzonosito); } public static void DeactivateMobileSession() { DeactivateOrganizationSystemSession(); } public static bool ActivateSystemSession() { if (UserContext.Instance == null || !UserContext.Instance.Activated) { SDAServer.Instance.SessionManager.ActivateSystemSession(); return true; } return false; } public static void DeactivateSystemSession() { if (UserContext.Instance != null && UserContext.Instance.Activated) { SDAServer.Instance.SessionManager.DeactivateSystemSession(); } } public static bool ActivateServiceSystemSession(string connectionString) { if (UserContext.Instance == null || !UserContext.Instance.Activated) { SDAServer.Instance.SessionManager.ActivateServiceSystemSession(connectionString); return true; } return false; } public static void DeactivateServiceSystemSession() { if (UserContext.Instance != null && UserContext.Instance.Activated) { SDAServer.Instance.SessionManager.DeactivateServiceSystemSession(); } } #endregion public static SDAConnection GetReadOnlyConnection(string intezmenyAzonosito) { var sqlConnectionStringBuilder = new SqlConnectionStringBuilder(SDAServer.Instance.ConnectionManager.GetIntezmenyConnectionString(intezmenyAzonosito)) { ApplicationIntent = ApplicationIntent.ReadOnly }; return new SDAConnection(sqlConnectionStringBuilder.ToString()); } [Obsolete(@"A Kreta.Core.Extensions.SortingAndPaging-t kell használni model listákkal, mivel ezeket mostmár tudjuk sorbarendezni a GridParameters-el, így nincs szükség rá, hogy elmenjen a DataSet a Web-re ezért nincs is szükség itt sorrenezni őket!")] public static DataTable SortingAndPaging(DataTable dataTable, GridParameters gridParameters) { if (gridParameters == null) { return dataTable; } int rowCount = dataTable.Rows.Count; if (rowCount > 0) { string orderBy = gridParameters.OrderBy ?? ""; if (!string.IsNullOrWhiteSpace(orderBy.Trim())) { var comparer = new AlphanumComparator(); string[] orderByList = orderBy.Split(','); foreach (string strOrderBy in orderByList) { string[] strOrderByColType = strOrderBy.Trim().Split(' '); //A rendezés oszlopa string strOrderByCol = strOrderByColType[0]; //A rendezés típusa string strOrderByType; //A rendezés típusának beállítása. ASC, vagy DESC a tartalma if (strOrderByColType.Length > 1) { strOrderByType = strOrderByColType[1].IndexOf("ASC", StringComparison.OrdinalIgnoreCase) >= 0 ? "ASC" : "DESC"; } else { strOrderByType = "ASC"; } var tableName = dataTable.TableName; if (strOrderByType == "ASC") { dataTable = dataTable.AsEnumerable().OrderBy(x => ToString(x[strOrderByCol]), comparer).CopyToDataTable(); } else { dataTable = dataTable.AsEnumerable().OrderByDescending(x => ToString(x[strOrderByCol]), comparer).CopyToDataTable(); } dataTable.TableName = tableName; } } if (gridParameters.FirstRow <= gridParameters.LastRow) { int pageSize = gridParameters.LastRow - gridParameters.FirstRow + 1; if (pageSize < rowCount) { dataTable = dataTable.AsEnumerable().Skip(gridParameters.FirstRow).Take(pageSize).CopyToDataTable(); } } } if (gridParameters.LoadResultSetInfo && !dataTable.ExtendedProperties.ContainsKey("RowCount")) { dataTable.ExtendedProperties.Add("RowCount", rowCount); } return dataTable; } public static DataSet AsDataSet(this DataTable dataTable) { if (dataTable.DataSet == null) { var dataSet = new DataSet(); dataSet.Tables.Add(dataTable); } return dataTable.DataSet; } public static DataTable GetData(SDACommand command, GridParameters gridParameters) { using (var adapter = new SDADataAdapter()) { adapter.SelectCommand = command; string mOriginalcommandtext = command.CommandText; string orderBy = gridParameters.OrderBy ?? ""; GenerateOrderString(command, ref orderBy, out string fullinnerfilter); if (!string.IsNullOrWhiteSpace(fullinnerfilter) || !string.IsNullOrWhiteSpace(orderBy)) { command.CommandText = string.Format(@" SELECT szurttabla.* FROM ( {0} ) szurttabla {1}", mOriginalcommandtext, fullinnerfilter ?? ""); } //Ha van rendezési feltétel if (!string.IsNullOrWhiteSpace(orderBy)) { command.CommandText += string.Format(" order by {0}", orderBy); } //Feltoltes a sorok szamanak lekerdezesevel egyutt var table = new DataTable(); if (gridParameters.LoadResultSetInfo && !table.ExtendedProperties.ContainsKey("RowCount")) { table.ExtendedProperties.Add("RowCount", GetRowCount(command)); } int firstRow = gridParameters.FirstRow; int lastRow = gridParameters.LastRow == -1 ? SDAServer.Instance.Configuration.MaximalRecordCountPerRequest - 1 : gridParameters.LastRow; bool reduceDbLoadEnabled = false; // optimalizált lekérdezés template - csak a szükséges sorokat kéri majd le az adapter // ha engedélyezve van és ha van értelme (azaz a kért utolsó sor különbözik a max. sortól) if (lastRow < SDAServer.Instance.Configuration.MaximalRecordCountPerRequest - 1) { reduceDbLoadEnabled = true; // ORACLE // subquery-ben nem lehet order by bool canWrap = !(mOriginalcommandtext.Contains("order by") || mOriginalcommandtext.Contains("ORDER BY")); if (canWrap) { command.CommandText = string.Format(@" select * from ( select row_number() over(order by {0}) as rnum_, szurttabla.* from ( {1} ) szurttabla {2} ) qqq where qqq.rnum_ between {3} and {4}", !string.IsNullOrWhiteSpace(orderBy.Trim()) ? orderBy : "(select 0)", mOriginalcommandtext, fullinnerfilter, firstRow + 1, lastRow + 1); } // nem tudunk optimalizálni else { reduceDbLoadEnabled = false; } } #region Language //nyelvesites (c_name,c_name_1........) //SetMultilanguage(command); #endregion Language //Lekerdezes lefuttatasa if (reduceDbLoadEnabled) adapter.Fill(table); else adapter.Fill(table, (int)firstRow, (int)lastRow); //ne legyen benne datasetben if (table.DataSet != null) { table.DataSet.Tables.Remove(table); } // osszes mezore beallitom, hogy adatbazisbol jott var cols = new List(); foreach (DataColumn col in table.Columns) { cols.Add(col.ColumnName.ToUpper()); } table.ExtendedProperties["DatabaseColumns"] = cols; return table; } } public static int CheckRowCount(SDACommand command) { command.CommandType = CommandType.Text; command.Connection = UserContext.Instance.SDAConnection; command.Transaction = UserContext.Instance.SDATransaction; using (var adapter = new SDADataAdapter()) { adapter.SelectCommand = command; return GetRowCount(command); } } private static void GenerateOrderString(SDACommand command, ref string orderBy, out string fullinnerfilter) { const string orderFormatString = @" CASE WHEN (LEN({0}) < 10 AND {0} NOT LIKE '%[^0-9]%') OR (LEN({0}) = 10 AND ISDATE({0}) = 1) THEN CAST({0} AS INT) ELSE CASE WHEN LEFT({0}, 1) BETWEEN '0' AND '9' AND {0} LIKE '%[^0-9]%' THEN CAST(LEFT(SUBSTRING(CONVERT(VARCHAR, {0}), 1, ISNULL(PATINDEX('%[^0-9]%', CONVERT(VARCHAR, {0})), 0) - 1),9) AS INT) ELSE 2147483647 END END {1}, {0} {1}"; //Ha van rendezési feltétel fullinnerfilter = ""; if (!string.IsNullOrWhiteSpace(orderBy.Trim())) { //Több rendezési szempont esetén felbontjuk az egyes oszlopokra string[] orderByList = orderBy.Split(','); //OrderBy-t ürítjük, majd újra összerakjuk a DNAME oszlopok miatt orderBy = ""; //Számoljuk a DNAME-es rendezési szempontok számát int dnameNo = 0; //Végigmegyünk a rendezési szempontokon foreach (string strOrderBy in orderByList) { //A végső order by kifejezés tárolásához szükséges változó string strTempOrderBy = ""; string[] strOrderByColType = strOrderBy.Trim().Split(' '); //A rendezés oszlopa string strOrderByCol = strOrderByColType[0]; //A rendezés típusa string strOrderByType; //A rendezés típusának beállítása. ASC, vagy DESC a tartalma if (strOrderByColType.Length > 1) { strOrderByType = strOrderByColType[1].IndexOf("ASC", StringComparison.OrdinalIgnoreCase) >= 0 ? " ASC" : " DESC"; } else { strOrderByType = " ASC"; } //Ha az aktuális rendezési szempont DNAME-es oszlop, akkor nyelvesítjük //és hozzákapcsolunk egy DictionaryItemBase táblát if (!string.IsNullOrWhiteSpace(strOrderByCol) && strOrderByCol.IndexOf("_DNAME", StringComparison.OrdinalIgnoreCase) >= 0) { //leszedem a DNAME-et mert igy kapom meg az oszlopnevet amivel joinolok string DNAME = Regex.Replace(strOrderByCol, "_DNAME", "", RegexOptions.IgnoreCase); //A tábla neve string strTableName = "t_dictionaryitembase"; //A tábla alias-a, hogy több DNAME-es oszloppal is működjön string strTableAlias = "dict" + dnameNo.ToString(); strTempOrderBy = string.Format(orderFormatString, $"{strTableAlias}.c_name", strOrderByType); fullinnerfilter += string.Format(" left join {0} {1} on {1}.id = szurttabla.{2}", strTableName, strTableAlias, DNAME); //Megöveljük a DNAME-es rendezési szempontok számlálóját dnameNo++; } // Ha az aktuális rendezési szempont BNAME-es oszlop else if (!string.IsNullOrWhiteSpace(strOrderByCol) && strOrderByCol.IndexOf("_BNAME", StringComparison.OrdinalIgnoreCase) >= 0) { //leszedem a BNAME-et mert igy kapom meg az oszlopnevet amivel joinolok string BNAME = Regex.Replace(strOrderByCol, "_BNAME", "", RegexOptions.IgnoreCase); if (strOrderByType.Equals(" ASC", StringComparison.OrdinalIgnoreCase)) { strTempOrderBy = BNAME + " asc"; } else { strTempOrderBy = BNAME + " desc"; } } else if (!string.IsNullOrWhiteSpace(strOrderByCol)) { if (command.CommandText.Contains($"[\"]{strOrderByCol}[\"]")) { strTempOrderBy = string.Format(orderFormatString, $"\"{strOrderByCol}\"", strOrderByType); } else { strTempOrderBy = string.Format(orderFormatString, strOrderByCol, strOrderByType); } } //Ha nincs benne a lekérdezésben az az oszlop, amire rendezünk, akkor nem lehet //ez alapján rendezni, nem adjuk hozzá else { strTempOrderBy = ""; } //Végső, teljes OrderBy rész összerakása if (!string.IsNullOrWhiteSpace(strTempOrderBy)) orderBy += strTempOrderBy + ","; } orderBy = orderBy.TrimEnd(','); } } private static int GetRowCount(SDACommand command) { string oldCommandText = command.CommandText; //utolso where helye int lastIndexOfWhere = command.CommandText.LastIndexOf("where", StringComparison.OrdinalIgnoreCase) == -1 ? 0 : command.CommandText.LastIndexOf("where", StringComparison.OrdinalIgnoreCase); //utolso orderby helye int lastIndexOfOrderBy = command.CommandText.LastIndexOf("order by", StringComparison.OrdinalIgnoreCase) == -1 ? command.CommandText.Length : command.CommandText.LastIndexOf("order by", StringComparison.OrdinalIgnoreCase); //levagom az order by-os végét, ha az a legutolsó if (lastIndexOfOrderBy > lastIndexOfWhere) { command.CommandText = command.CommandText.Substring(0, lastIndexOfOrderBy); } command.CommandText = "SELECT COUNT(1) FROM ( " + command.CommandText + " ) ttt"; int rowsCount = Convert.ToInt32(command.ExecuteScalar()); command.CommandText = oldCommandText; return rowsCount; } public static string ToString(object data) { try { return ((data == null) || (data == DBNull.Value)) ? string.Empty : data.ToString(); } catch { return string.Empty; } } public static int ToInt32(object data) { try { return ((data == null) || (data == DBNull.Value) || string.IsNullOrWhiteSpace(data.ToString())) ? 0 : Convert.ToInt32(data); } catch { return 0; } } } internal class AlphanumComparator : IComparer { private enum ChunkType { Alphanumeric, Numeric }; private bool InChunk(char ch, char otherCh) { ChunkType type = ChunkType.Alphanumeric; if (char.IsDigit(otherCh)) { type = ChunkType.Numeric; } if ((type == ChunkType.Alphanumeric && char.IsDigit(ch)) || (type == ChunkType.Numeric && !char.IsDigit(ch))) { return false; } return true; } public int Compare(T x, T y) { if (!(x is string s1) || !(y is string s2) || (s1 == null) || (s2 == null)) { return 0; } int thisMarker = 0; int thatMarker = 0; while ((thisMarker < s1.Length) || (thatMarker < s2.Length)) { if (thisMarker >= s1.Length) { return -1; } if (thatMarker >= s2.Length) { return 1; } char thisCh = s1[thisMarker]; char thatCh = s2[thatMarker]; var thisChunk = new StringBuilder(); var thatChunk = new StringBuilder(); while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || InChunk(thisCh, thisChunk[0]))) { thisChunk.Append(thisCh); thisMarker++; if (thisMarker < s1.Length) { thisCh = s1[thisMarker]; } } while ((thatMarker < s2.Length) && (thatChunk.Length == 0 || InChunk(thatCh, thatChunk[0]))) { thatChunk.Append(thatCh); thatMarker++; if (thatMarker < s2.Length) { thatCh = s2[thatMarker]; } } int result = 0; // If both chunks contain numeric characters, sort them numerically if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0])) { if (int.TryParse(thisChunk.ToString(), out int thisIntNumericChunk) && int.TryParse(thatChunk.ToString(), out int thatIntNumericChunk)) { if (thisIntNumericChunk < thatIntNumericChunk) { result = -1; } if (thisIntNumericChunk > thatIntNumericChunk) { result = 1; } } else if (long.TryParse(thisChunk.ToString(), out long thisLongNumericChunk) && long.TryParse(thatChunk.ToString(), out long thatLongNumericChunk)) { if (thisLongNumericChunk < thatLongNumericChunk) { result = -1; } if (thisLongNumericChunk > thatLongNumericChunk) { result = 1; } } } else { result = thisChunk.ToString().CompareTo(thatChunk.ToString()); } if (result != 0) { return result; } } return 0; } } }