593 lines
22 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|