kreta/Kreta.DataAccessManual/Util/DataUtil.cs
2024-03-13 00:33:46 +01:00

593 lines
22 KiB
C#

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>-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>();
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<string>();
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<T> : IComparer<T>
{
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;
}
}
}