From aaf104a915bf108010a3d0bf0ec4cd0ddc9a16e2 Mon Sep 17 00:00:00 2001 From: SHM Date: Mon, 21 Apr 2025 12:00:24 +0900 Subject: [PATCH] =?UTF-8?q?[=EC=84=B1=ED=98=84=EB=AA=A8]=20Config=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80,=20Socket=20Recv=20Json?= =?UTF-8?q?,=20string=20=EA=B8=B0=EB=8A=A5=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Projects/DLL/SystemX.Core.dll | Bin 30720 -> 32256 bytes Projects/HubX/Config/HubX.WebApiConfig.json | 32 +++++ Projects/HubX/Config/log4net.config | 77 ++++++++++++ .../DBPatch/sqlScripts/dacpac/HubX.DB.dacpac | Bin 3046 -> 3048 bytes .../HubX/HubX.Library/Config/WebApiConfig.cs | 20 +++ .../HubX/HubX.Library/DataBase/DBManager.cs | 29 +++++ .../Socket/Packet/PacketHandler.cs | 48 ++++---- .../HubX.Library/Socket/Packet/Protocol.cs | 4 +- .../Socket/Packet/ServerPacketManager.cs | 27 +++-- Projects/HubX/HubX.Server/Program.cs | 98 ++++++++++----- .../HubX.Server/TaskManager/TaskSocket.cs | 29 +++++ Projects/HubX/HubX.sln | 9 +- .../Communication/Socket/Listener.cs | 21 ++-- .../{DB => Config/Model}/DataBase.cs | 2 +- .../SystemX.Core/Config/Model/Server.cs | 21 ++++ .../SystemX.Core/Config/WebCommonConfig.cs | 16 +++ .../SystemX.Core/DB/DBTransaction.cs | 107 ++++++++++++++++ .../SystemX.Core/SystemX.Core/DB/EFCore.cs | 114 ++++++------------ .../SystemX.Core/Log4net/Log4net.cs | 10 +- .../SystemX.Core/Services/ConfigService.cs | 39 ++++++ .../SystemX.Core/Utils/JsonUtils.cs | 3 +- 21 files changed, 550 insertions(+), 156 deletions(-) create mode 100644 Projects/HubX/Config/HubX.WebApiConfig.json create mode 100644 Projects/HubX/Config/log4net.config create mode 100644 Projects/HubX/HubX.Library/Config/WebApiConfig.cs create mode 100644 Projects/HubX/HubX.Library/DataBase/DBManager.cs create mode 100644 Projects/HubX/HubX.Server/TaskManager/TaskSocket.cs rename Projects/SystemX.Core/SystemX.Core/{DB => Config/Model}/DataBase.cs (95%) create mode 100644 Projects/SystemX.Core/SystemX.Core/Config/Model/Server.cs create mode 100644 Projects/SystemX.Core/SystemX.Core/Config/WebCommonConfig.cs create mode 100644 Projects/SystemX.Core/SystemX.Core/DB/DBTransaction.cs create mode 100644 Projects/SystemX.Core/SystemX.Core/Services/ConfigService.cs diff --git a/Projects/DLL/SystemX.Core.dll b/Projects/DLL/SystemX.Core.dll index 7515f20994d1af6b03382097d447394dd0399113..d8175ae8ecd26fb1d7f0fa9264f8110093c70370 100644 GIT binary patch literal 32256 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 YyNX+prqS0E^Z&a#{J(zwH(B8S0Z5{e>Hq)$ literal 30720 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 diff --git a/Projects/HubX/Config/HubX.WebApiConfig.json b/Projects/HubX/Config/HubX.WebApiConfig.json new file mode 100644 index 0000000..8e3987f --- /dev/null +++ b/Projects/HubX/Config/HubX.WebApiConfig.json @@ -0,0 +1,32 @@ +{ + "Server": { + "Address": "https://*", + "Port": 9000, + "IIS": false + }, + "Socket": { + "Address": "*", + "Port": 9010, + "IIS": false + }, + "DataBase": [ + { + "IP": "127.0.0.1", + "Port": 1433, + "DBName": "HubX", + "DBID": 1, + "DBContext": "HubXContext", + "UserID": "alis", + "Password": "Kefico!@34" + }, + { + "IP": "127.0.0.1", + "Port": 1433, + "DBName": "HubX_DEV", + "DBID": 2, + "DBContext": "HubXContext", + "UserID": "alis", + "Password": "Kefico!@34" + } + ] +} \ No newline at end of file diff --git a/Projects/HubX/Config/log4net.config b/Projects/HubX/Config/log4net.config new file mode 100644 index 0000000..0ab5109 --- /dev/null +++ b/Projects/HubX/Config/log4net.config @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Projects/HubX/DBPatch/sqlScripts/dacpac/HubX.DB.dacpac b/Projects/HubX/DBPatch/sqlScripts/dacpac/HubX.DB.dacpac index 1307ee6cda97b3986cd76b275b9ac800f68655b1..f2df8144f571944ff798ad7b8b18b152b6a7f6a3 100644 GIT binary patch delta 666 zcmV;L0%iT?7w8uZP)h>@6aWAK2mlvfu?+D90vBJi{{({p0vBJCga+sd7hjcHpdM;Q zDU)>vK7SqXgGV3&MuY^Zs-_buY4;A8#0ubyZK_Fst&4tAf1xG;+EkfU#RlJd&ppTI z+Wz(9XY}~m)W$a|B;##tA{&|pZ3|wqb|0Ias;t0#Oy0kXmZW$VY|mOl16moI2c=GP z0Az8X4Uu-k3c)3>lwI%!$d_7Dq1%Fz6ktOIBY!pfPLw7A7$OWHHg#9Sh}NVyl097u zexgD#DlcK3_lEi3>%`B~c`)h~|yJ-Q0lNC_zaxG#lCe z@EO~Us-?<;rx`eUhy zn14Da2!$TpA#4Q&3M>~FzC|1uSTn~#GeTVIqA~(g`D6wWD!~wY7IZC)wg}BVf9}p~ z90mxx;RhJbA?!u=g#&8UmUl4@@;&T3Bc?AK5PBbFSE$~h~3xrG795Lt^9){y!L5SF29YxTT#EM1R+;yIswSPxQRyN7}|a=u}=cs}L$ZNF1VV z{EPQi$~c9-J+={cY&4bsGoc}Rm6-hRxt~~ue%E>54mQdTv^dJHnQp@vFun*Do1oz( zt!;f1%_N-#3+(ud3}%aE;ACNny+xj`!W8MnEYDHy Av;Y7A delta 664 zcmV;J0%!f`7v>iXP)h>@6aWAK2mru9u?+D90>D7C{{({p0>D6%ga+sdz(AE+1h2+? zCzEvtK7XCy2k!_N5fY@Tnogvo-8*0sD}Xb$sV4okF8WFRg_;CtQ)N~a8+`9Q_Z**V z``3@3(c^1V8{epqjJL6gENB|EEqKY=eQb8Bng!-#^8Q`4B*n8}d)68n(8}06D0P|x zAd3TSh_o732rhZ0tb#W{zSNQm-4>Lj02?Y8sejpbqBIG>5McnZsk<6Rv?j%o?CDzY z6BUY4c?s*p*Q=()wqXB7UX z&$#A4lZM7-k24c|U%^`#daC)kp{?pw2)64K7t&178~Xrv1V!M!Ezz@HU0fW|A4^Td z)PFhgiCyieP7a218UWl_c5OB!vKw#zHC6~eUx3HdWVvy>7?}bT3gO*X>BgY$l4Nl z)Qgw;!59pQkvI7NU}RmbIzi)>c1jRkvw!Y(H7h>R^OhfJ8}Fc9xs_ibRJxGZMBDfm z@2!+^3VnNQA#7V{D*tCfL-Z;!`QLLtu?+pL^S&KylpSbslwC93hB07#5iB-A!%JFQ z`X-u5>IVyKdy5Qai)CPEVT#>Fp02_a>4l%?D7W(kc7uHBW+@J{AkAHzyPp2b(<)`I zZ_ChokaEi%J@r&qt)nm43L|hQuAd1oy%WiAP)h>@6aWAK2mru9liLa00>D6%xe7G` yz(AAm3OEA5K$9v9I|;x*m0AR^#(XD}ZVN90z(A9q3mgH>le`Ni2B``F0000TfHgJ% diff --git a/Projects/HubX/HubX.Library/Config/WebApiConfig.cs b/Projects/HubX/HubX.Library/Config/WebApiConfig.cs new file mode 100644 index 0000000..45e1939 --- /dev/null +++ b/Projects/HubX/HubX.Library/Config/WebApiConfig.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; +using SystemX.Core.Config; +using SystemX.Core.Config.Model; + +namespace HubX.Library.Config +{ + public class WebApiConfig : WebCommonConfig + { + [JsonPropertyName("DataBase")] + public List? DataBase { get; set; } + + [JsonPropertyName("Socket")] + public Server Socket { get; set; } + } +} diff --git a/Projects/HubX/HubX.Library/DataBase/DBManager.cs b/Projects/HubX/HubX.Library/DataBase/DBManager.cs new file mode 100644 index 0000000..6696e6f --- /dev/null +++ b/Projects/HubX/HubX.Library/DataBase/DBManager.cs @@ -0,0 +1,29 @@ +using Azure.Core; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HubX.Library.DataBase +{ + public class DBManager + { + public DBManager() + { + } + + public async Task Insert(T context) where T : DbContext + { + //using (var transaction = await context.CreateTransactionAsync()) + //{ + // if (context.TCertificates.ToList().Exists(x => x.CCuid == tbscsr.CCuid) == false) + // { + // await context.AddAsync(certificate); + // } + // transactionResult = await context.CloseTransactionAsync(transaction); + //} + } + } +} diff --git a/Projects/HubX/HubX.Library/Socket/Packet/PacketHandler.cs b/Projects/HubX/HubX.Library/Socket/Packet/PacketHandler.cs index 245a75d..2a41316 100644 --- a/Projects/HubX/HubX.Library/Socket/Packet/PacketHandler.cs +++ b/Projects/HubX/HubX.Library/Socket/Packet/PacketHandler.cs @@ -13,31 +13,37 @@ namespace HubX.Library.Socket.Packet public class PacketHandler { - public static void C2S_INSERT_UniqueKeyHandler(PacketSession session, IMessage packet) - { - C2S_INSERT_UniqueKey movePacket = packet as C2S_INSERT_UniqueKey; - ClientSession clientSession = session as ClientSession; + public static void C2S_INSERT_UniqueKeyHandler(PacketSession session, ArraySegment buffer) + { + var recvData = Encoding.UTF8.GetString(buffer); + + //convert to object + var jsonObject = recvData.ToObject(); + if (jsonObject == null) + { + var recvDataList = recvData.Split(","); + + jsonObject = new C2S_INSERT_UniqueKey + { + Identity = recvDataList[0], + Data1 = recvDataList[1], + Data2 = recvDataList[2], + Data3 = recvDataList[3], + Data4 = recvDataList[4], + Data5 = recvDataList[5], + }; + } + //insert DB + if(jsonObject != null) + { + + } + + ClientSession clientSession = session as ClientSession; Client client = clientSession.Client; if (client == null) return; } - - public static void C_SkillHandler(PacketSession session, IMessage packet) - { - //C_Skill skillPacket = packet as C_Skill; - //ClientSession clientSession = session as ClientSession; - - //Player player = clientSession.MyPlayer; - //if (player == null) - // return; - - //GameRoom room = player.Room; - //if (room == null) - // return; - - //room.Push(room.HandleSkill, player, skillPacket); - } } - } diff --git a/Projects/HubX/HubX.Library/Socket/Packet/Protocol.cs b/Projects/HubX/HubX.Library/Socket/Packet/Protocol.cs index 3909a35..4c5b696 100644 --- a/Projects/HubX/HubX.Library/Socket/Packet/Protocol.cs +++ b/Projects/HubX/HubX.Library/Socket/Packet/Protocol.cs @@ -12,12 +12,12 @@ namespace HubX.Library.Socket.Packet public class C2S : IMessage { - public EnumMessageId MessageId { get; set; } + // public EnumMessageId MessageId { get; set; } } public class S2C : IMessage { - public EnumMessageId MessageId { get; set; } + // public EnumMessageId MessageId { get; set; } public EnumMessageResult Result { get; set; } } diff --git a/Projects/HubX/HubX.Library/Socket/Packet/ServerPacketManager.cs b/Projects/HubX/HubX.Library/Socket/Packet/ServerPacketManager.cs index 62e5426..79b7da6 100644 --- a/Projects/HubX/HubX.Library/Socket/Packet/ServerPacketManager.cs +++ b/Projects/HubX/HubX.Library/Socket/Packet/ServerPacketManager.cs @@ -20,9 +20,9 @@ namespace HubX.Library.Socket.Packet } Dictionary, ushort>> _onRecv = new Dictionary, ushort>>(); - Dictionary> _handler = new Dictionary>(); + Dictionary>> _handler = new Dictionary>>(); - public Action CustomHandler { get; set; } + public Action, ushort> CustomHandler { get; set; } public void Register() { @@ -39,31 +39,34 @@ namespace HubX.Library.Socket.Packet ushort id = BitConverter.ToUInt16(buffer.Array, buffer.Offset + count); count += 2; - Action, ushort> action = null; - if (_onRecv.TryGetValue(id, out action)) - action.Invoke(session, buffer, id); + ushort packetSize = (ushort)(buffer.Count - count); + byte[] packet = new byte[packetSize]; + Array.Copy(buffer.ToArray(), count, packet, 0, packetSize); + + if (_onRecv.TryGetValue(id, out var action)) + action.Invoke(session, packet, id); } - void MakePacket(PacketSession session, ArraySegment buffer, ushort id) where T : IMessage, new() + void MakePacket(PacketSession session, ArraySegment buffer, ushort id) where T : new() { - T pkt = new T(); + // T pkt = new T(); //pkt.MergeFrom(buffer.Array, buffer.Offset + 4, buffer.Count - 4); if (CustomHandler != null) { - CustomHandler.Invoke(session, pkt, id); + CustomHandler.Invoke(session, buffer, id); } else { - Action action = null; + Action> action = null; if (_handler.TryGetValue(id, out action)) - action.Invoke(session, pkt); + action.Invoke(session, buffer); } } - public Action GetPacketHandler(ushort id) + public Action> GetPacketHandler(ushort id) { - Action action = null; + Action> action = null; if (_handler.TryGetValue(id, out action)) return action; return null; diff --git a/Projects/HubX/HubX.Server/Program.cs b/Projects/HubX/HubX.Server/Program.cs index 797a699..0654f85 100644 --- a/Projects/HubX/HubX.Server/Program.cs +++ b/Projects/HubX/HubX.Server/Program.cs @@ -1,7 +1,23 @@ +using HubX.Library.Config; using HubX.Library.Socket.Session; using HubX.Server; +using HubX.Server.TaskManager; using System.Net; +using System.Net.Sockets; using SystemX.Core.Communication; +using SystemX.Core.Services; + +string configDir = @"../Config"; + +//raed log4net config +if (Log4net.IsConfigLoad == true) +{ + Log4net.WriteLine("Log4net Init Success"); +} +else +{ + Log4net.WriteLine("Log4net Init Failed", LogType.Error); +} var builder = WebApplication.CreateBuilder(args); @@ -12,41 +28,61 @@ builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); +//singleton +builder.Services.AddSingleton>(); + +//config preload +ConfigService preloadConfig = new ConfigService(); +if (preloadConfig.OpenConfig($@"{configDir}/HubX.WebApiConfig.json") == true) +{ + var config = preloadConfig.GetConfig(); +} +else +{ + Console.WriteLine("Config Preload Load Error."); + return; +} + var app = builder.Build(); +//read api config and set +string serverUrl = string.Empty; +var configService = app.Services.GetService>(); +bool isIIS = false; + +int socketPort = 0; + +if (configService?.OpenConfig($@"{configDir}/HubX.WebApiConfig.json") == true) +{ + Log4net.WriteLine("WebApi Config Success."); + var apiConfig = ConfigService.Config; + if (apiConfig != null) + { + serverUrl = $"{apiConfig.Server.Address}:{apiConfig.Server.Port}"; + isIIS = apiConfig.Server.IIS; + + //socket + socketPort = apiConfig.Socket.Port; + } +} +else +{ + Log4net.WriteLine("WebApi Config Error."); + return; +} + // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { + Log4net.WriteLine($"IsDevelopment:{app.Environment.IsDevelopment()}"); + Log4net.WriteLine($"Swagger Url: {serverUrl}/swagger"); + app.UseSwagger(); app.UseSwaggerUI(); } -Log4net.WriteLine("Run"); -Log4net.WriteLine("Custom LogLevel",LogType.DB); - -WeatherForecast weatherForecast = new WeatherForecast(); -weatherForecast.Summary = "so hot"; -var strJson = weatherForecast.ToJson(); - -var deep = weatherForecast.DeepCopy(); -deep.Summary = "so cool"; - -var rr = strJson.ToObject(); - -Task.Run(async() => -{ - await Task.Delay(2000); - Listener _listener = new Listener(); - - // string host = Dns.GetHostName(); - IPHostEntry ipHost = Dns.GetHostEntry("127.0.0.1"); - IPAddress ipAddr = ipHost.AddressList[0]; - IPEndPoint endPoint = new IPEndPoint(ipAddr, 7777); - - _listener.Init(endPoint, () => { return SessionManager.Instance.Generate(); }); - - Console.WriteLine("Listening..."); -}); +TaskSocket taskSocket = new TaskSocket(); +taskSocket?.Run(socketPort); app.UseHttpsRedirection(); @@ -54,4 +90,12 @@ app.UseAuthorization(); app.MapControllers(); -app.Run(); +if (isIIS == true) +{ + app.Run(); +} +else +{ + Log4net.WriteLine($"Operation Url: {serverUrl}"); + app.Run($"{serverUrl}"); +} diff --git a/Projects/HubX/HubX.Server/TaskManager/TaskSocket.cs b/Projects/HubX/HubX.Server/TaskManager/TaskSocket.cs new file mode 100644 index 0000000..bf1b709 --- /dev/null +++ b/Projects/HubX/HubX.Server/TaskManager/TaskSocket.cs @@ -0,0 +1,29 @@ +using HubX.Library.Socket.Session; +using System.Net; +using SystemX.Core.Communication; + +namespace HubX.Server.TaskManager +{ + public class TaskSocket + { + public async Task Run(int socketPort = 7777) + { + try + { + await Task.Delay(1000); + Listener _listener = new Listener(); + IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, socketPort); + + _listener.Init(endPoint, () => { return SessionManager.Instance.Generate(); }); + + Log4net.WriteLine($"Address:{endPoint.Address}, Port:{socketPort}", LogType.SOCKET); + Log4net.WriteLine($"Socket Listening Start", LogType.SOCKET); + } + catch (Exception e) + { + Log4net.WriteLine("Socket Run Failed",LogType.Error); + Log4net.WriteLine(e); + } + } + } +} diff --git a/Projects/HubX/HubX.sln b/Projects/HubX/HubX.sln index 555a145..0401d4e 100644 --- a/Projects/HubX/HubX.sln +++ b/Projects/HubX/HubX.sln @@ -7,9 +7,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HubX.Server", "HubX.Server\ EndProject Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "HubX.DB", "HubX.DB\HubX.DB.sqlproj", "{514DDCCF-6B50-49F8-B212-70498396CF19}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HubX.Library", "HubX.Library\HubX.Library.csproj", "{E6FA1D27-A644-4E50-BF16-DCCA59AA378D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HubX.Library", "HubX.Library\HubX.Library.csproj", "{E6FA1D27-A644-4E50-BF16-DCCA59AA378D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HubX.Library.DB", "HubX.Library.DB\HubX.Library.DB.csproj", "{C43CF1F1-9CB0-44DC-89D7-3514F18EAD46}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HubX.Library.DB", "HubX.Library.DB\HubX.Library.DB.csproj", "{C43CF1F1-9CB0-44DC-89D7-3514F18EAD46}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Config", "Config", "{18B1BDDB-B76F-43A4-BBE8-805CEEF35CE0}" + ProjectSection(SolutionItems) = preProject + Config\HubX.WebApiConfig.json = Config\HubX.WebApiConfig.json + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Listener.cs b/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Listener.cs index ed7d124..a118396 100644 --- a/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Listener.cs +++ b/Projects/SystemX.Core/SystemX.Core/Communication/Socket/Listener.cs @@ -43,16 +43,23 @@ namespace SystemX.Core.Communication void OnAcceptCompleted(object sender, SocketAsyncEventArgs args) { - if (args.SocketError == SocketError.Success) + try { - Session session = _sessionFactory.Invoke(); - session.Start(args.AcceptSocket); - session.OnConnected(args.AcceptSocket.RemoteEndPoint); + if (args.SocketError == SocketError.Success) + { + Session session = _sessionFactory.Invoke(); + session.Start(args.AcceptSocket); + session.OnConnected(args.AcceptSocket.RemoteEndPoint); + } + else + { + Log4net.WriteLine(args.SocketError.ToString(), LogType.Error); + } } - else + catch(Exception e) { - Log4net.WriteLine(args.SocketError.ToString(), LogType.Error); - } + Log4net.WriteLine(e, LogType.Error); + } RegisterAccept(args); } diff --git a/Projects/SystemX.Core/SystemX.Core/DB/DataBase.cs b/Projects/SystemX.Core/SystemX.Core/Config/Model/DataBase.cs similarity index 95% rename from Projects/SystemX.Core/SystemX.Core/DB/DataBase.cs rename to Projects/SystemX.Core/SystemX.Core/Config/Model/DataBase.cs index 8080bea..9f7706d 100644 --- a/Projects/SystemX.Core/SystemX.Core/DB/DataBase.cs +++ b/Projects/SystemX.Core/SystemX.Core/Config/Model/DataBase.cs @@ -5,7 +5,7 @@ using System.Text; using System.Text.Json.Serialization; using System.Threading.Tasks; -namespace SystemX.Core.DB +namespace SystemX.Core.Config.Model { public class DataBase { diff --git a/Projects/SystemX.Core/SystemX.Core/Config/Model/Server.cs b/Projects/SystemX.Core/SystemX.Core/Config/Model/Server.cs new file mode 100644 index 0000000..937a168 --- /dev/null +++ b/Projects/SystemX.Core/SystemX.Core/Config/Model/Server.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace SystemX.Core.Config.Model +{ + public class Server + { + [JsonPropertyName("Address")] + public string? Address { get; set; } + + [JsonPropertyName("Port")] + public int Port { get; set; } + + [JsonPropertyName("IIS")] + public bool IIS { get; set; } + } +} diff --git a/Projects/SystemX.Core/SystemX.Core/Config/WebCommonConfig.cs b/Projects/SystemX.Core/SystemX.Core/Config/WebCommonConfig.cs new file mode 100644 index 0000000..15003a0 --- /dev/null +++ b/Projects/SystemX.Core/SystemX.Core/Config/WebCommonConfig.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; +using SystemX.Core.Config.Model; + +namespace SystemX.Core.Config +{ + public class WebCommonConfig + { + [JsonPropertyName("Server")] + public Server Server { get; set; } = new(); + } +} diff --git a/Projects/SystemX.Core/SystemX.Core/DB/DBTransaction.cs b/Projects/SystemX.Core/SystemX.Core/DB/DBTransaction.cs new file mode 100644 index 0000000..90ef9b7 --- /dev/null +++ b/Projects/SystemX.Core/SystemX.Core/DB/DBTransaction.cs @@ -0,0 +1,107 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SystemX.Core.Config.Model; + +namespace SystemX.Core.DB +{ + public static class DBTransaction + { + /// + /// Get SqlServer Connection String + /// + public static string ConvertToConnectionString(this DataBase dbConfig) + { + return $"server={dbConfig.IP},{dbConfig.Port}; user id={dbConfig.UserID}; password={dbConfig.Password}; database={dbConfig.DBName}; TrustServerCertificate=true;"; + } + + public static IEnumerable? GetEntity(this DbContext dbContext) where TEntity : class + { + IEnumerable? entity = default; + + var type = dbContext.GetType(); + try + { + foreach (var prop in type.GetProperties()) + { + string propertyFullName = $"{prop.PropertyType.FullName}"; + if (propertyFullName.ToLower().Contains(typeof(TEntity).Name.ToLower())) + { + entity = prop.GetValue(dbContext) as IEnumerable; + break; + } + } + } + catch (Exception ex) + { + Log4net.WriteLine(ex); + } + + return entity; + } + + #region Transaction + public static IDbContextTransaction CreateTransaction(this DbContext dbContext) + { + return dbContext.Database.BeginTransaction(); + } + + public static bool CloseTransaction(this DbContext dbContext, IDbContextTransaction transaction) + { + bool result = false; + try + { + dbContext.SaveChanges(); + transaction.Commit(); + result = true; + + Log4net.WriteLine("Transaction Commit", LogType.Debug); + } + catch (Exception ex) + { + transaction.Rollback(); + Log4net.WriteLine("Transaction Rollback", LogType.Error); + Log4net.WriteLine(ex); + } + transaction.Dispose(); + + return result; + } + #endregion + + #region Transaction Async + public static async Task CreateTransactionAsync(this DbContext dbContext) + { + return await dbContext.Database.BeginTransactionAsync(); + } + + public static async Task CloseTransactionAsync(this DbContext dbContext, IDbContextTransaction transaction) + { + bool result = false; + try + { + await dbContext.SaveChangesAsync(); + await transaction.CommitAsync(); + result = true; + + Log4net.WriteLine("Transaction Commit", LogType.Debug); + } + catch (Exception ex) + { + await transaction.RollbackAsync(); + Log4net.WriteLine("Transaction Rollback", LogType.Error); + Log4net.WriteLine(ex); + } + await transaction.DisposeAsync(); + + return result; + } + #endregion + } + + +} diff --git a/Projects/SystemX.Core/SystemX.Core/DB/EFCore.cs b/Projects/SystemX.Core/SystemX.Core/DB/EFCore.cs index bb3a997..5045be6 100644 --- a/Projects/SystemX.Core/SystemX.Core/DB/EFCore.cs +++ b/Projects/SystemX.Core/SystemX.Core/DB/EFCore.cs @@ -1,106 +1,64 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using SystemX.Core.Config.Model; namespace SystemX.Core.DB { - public static class EFCore + public class EFCore { - /// - /// Get SqlServer Connection String - /// - public static string ConvertToConnectionString(this DataBase dbConfig) - { - return $"server={dbConfig.IP},{dbConfig.Port}; user id={dbConfig.UserID}; password={dbConfig.Password}; database={dbConfig.DBName}; TrustServerCertificate=true;"; + private readonly Dictionary DicDbContext = new Dictionary(); + + public EFCore() + : base() + { } - public static IEnumerable? GetEntity(this DbContext dbContext) where TEntity : class - { - IEnumerable? entity = default; - - var type = dbContext.GetType(); - try - { - foreach (var prop in type.GetProperties()) - { - string propertyFullName = $"{prop.PropertyType.FullName}"; - if (propertyFullName.ToLower().Contains(typeof(TEntity).Name.ToLower())) - { - entity = prop.GetValue(dbContext) as IEnumerable; - break; - } - } - } - catch (Exception ex) - { - Log4net.WriteLine(ex); - } - - return entity; + #region Initialize DBContext + private void InitializeDB() where TDBContext : DbContext, new() + { + //if (dbList is not null) + //{ + // foreach (var db in dbList) + // { + // if (typeof(VpkiAccountDbContext).Name == db.DBContext) + // { + // CreateDBContext(db); + // } + // else if (typeof(VpkiDataDbContext).Name == db.DBContext) + // { + // CreateDBContext(db); + // } + // } + //} } - #region Transaction - public static IDbContextTransaction CreateTransaction(this DbContext dbContext) + private void CreateDBContext(DataBase? dbConfig) where TDBContext : DbContext, new() { - return dbContext.Database.BeginTransaction(); - } + //var connectionString = dbConfig?.ConvertToConnectionString(); - public static bool CloseTransaction(this DbContext dbContext, IDbContextTransaction transaction) - { - bool result = false; - try - { - dbContext.SaveChanges(); - transaction.Commit(); - result = true; + //var dbContext = new TDBContext(); + //dbContext.Database.SetConnectionString($"{connectionString}"); - Log4net.WriteLine("Transaction Commit", LogType.Debug); - } - catch (Exception ex) - { - transaction.Rollback(); - Log4net.WriteLine("Transaction Rollback", LogType.Error); - Log4net.WriteLine(ex); - } - transaction.Dispose(); - - return result; + //if (dbContext is not null) + // DicDbContext.Add($"{dbConfig?.DBContext}_{dbConfig?.DBID}", dbContext); } #endregion - #region Transaction Async - public static async Task CreateTransactionAsync(this DbContext dbContext) + public TDBContext? GetDBContext(int dbID = 1) where TDBContext : DbContext { - return await dbContext.Database.BeginTransactionAsync(); - } + TDBContext? dBContext = default; - public static async Task CloseTransactionAsync(this DbContext dbContext, IDbContextTransaction transaction) - { - bool result = false; - try + var dbContextType = typeof(TDBContext); + if (DicDbContext.TryGetValue($"{dbContextType.Name}_{dbID}", out var context) == true) { - await dbContext.SaveChangesAsync(); - await transaction.CommitAsync(); - result = true; - - Log4net.WriteLine("Transaction Commit", LogType.Debug); + dBContext = context as TDBContext; } - catch (Exception ex) - { - await transaction.RollbackAsync(); - Log4net.WriteLine("Transaction Rollback", LogType.Error); - Log4net.WriteLine(ex); - } - await transaction.DisposeAsync(); - return result; + return dBContext; } - #endregion } - - } diff --git a/Projects/SystemX.Core/SystemX.Core/Log4net/Log4net.cs b/Projects/SystemX.Core/SystemX.Core/Log4net/Log4net.cs index 8d10913..34bb330 100644 --- a/Projects/SystemX.Core/SystemX.Core/Log4net/Log4net.cs +++ b/Projects/SystemX.Core/SystemX.Core/Log4net/Log4net.cs @@ -54,13 +54,15 @@ public static class Log4net static Log4net() { - Console.WriteLine("log4net constructor"); - if (File.Exists("./log4net.config") == false) + string log4netConfigPath = @"../Config/log4net.config"; + + if (File.Exists(log4netConfigPath) == false) { - File.WriteAllText("log4net.config", Config); + Console.WriteLine($"create log4netConfig: {log4netConfigPath}"); + File.WriteAllText(log4netConfigPath, Config); } - IsConfigLoad = OpenConfig(@"./log4net.config"); + IsConfigLoad = OpenConfig(log4netConfigPath); } private static bool OpenConfig(string path) diff --git a/Projects/SystemX.Core/SystemX.Core/Services/ConfigService.cs b/Projects/SystemX.Core/SystemX.Core/Services/ConfigService.cs new file mode 100644 index 0000000..22d45fa --- /dev/null +++ b/Projects/SystemX.Core/SystemX.Core/Services/ConfigService.cs @@ -0,0 +1,39 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using SystemX.Core.Config; + +namespace SystemX.Core.Services +{ + public class ConfigService where T : WebCommonConfig + { + public static T? Config { get; set; } + + public bool OpenConfig(string path) + { + bool result = true; + + try + { + string clientConfigJson = File.ReadAllText(path); + Config = JsonConvert.DeserializeObject(clientConfigJson); + } + catch (Exception e) + { + Console.WriteLine("Config Init Error"); + Console.WriteLine(e.Message); + result = false; + } + + return result; + } + + public T? GetConfig() + { + return Config; + } + } +} diff --git a/Projects/SystemX.Core/SystemX.Core/Utils/JsonUtils.cs b/Projects/SystemX.Core/SystemX.Core/Utils/JsonUtils.cs index 4cda787..16ae4c1 100644 --- a/Projects/SystemX.Core/SystemX.Core/Utils/JsonUtils.cs +++ b/Projects/SystemX.Core/SystemX.Core/Utils/JsonUtils.cs @@ -32,8 +32,7 @@ public static class JsonUtils } catch(Exception e) { - Log4net.WriteLine("JsonUtils.ToObject()", LogType.Error); - Log4net.WriteLine(e); + Log4net.WriteLine("JsonUtils.ToObject()", LogType.Warn); } return result;