From b78e5a23ea39fcad6eb7f19fe91e5ca26a2299de Mon Sep 17 00:00:00 2001 From: SHM Date: Thu, 30 Oct 2025 16:51:52 +0900 Subject: [PATCH] =?UTF-8?q?[=EC=84=B1=ED=98=84=EB=AA=A8]=20CPMeta=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sqlScripts/SystemX.DB.CPMeta_Create.sql | 16 +- .../sqlScripts/SystemX.DB.CPMeta_Update.sql | 61 ++++- .../dacpac/SystemX.DB.CPMeta.dacpac | Bin 2653 -> 2679 bytes .../WebApi.Project.UniqueKeyApi.Config.json | 12 +- Projects/DLL/SystemX.Core.DB.dll | Bin 75776 -> 75776 bytes .../SystemX.DB.CPMeta.sqlproj | 3 +- .../dbo/{ => Tables}/tWbmsMeta.sql | 6 +- .../CPMeta/Context/CPMetaContext.cs | 7 +- .../SystemX.Core.DB/CPMeta/Tables/tWbms.cs | 4 +- .../WebApi/AuthApi/Services/AuthService.cs | 2 +- .../WebApi.Library/Enums/WebApiResult.cs | 1 + .../Controllers/CPMetaController.cs | 70 +++++ .../Controllers/UniqueKeyController.cs | 108 ++++---- .../Models/Packet.cs | 49 +++- .../WebApi.Project.UniqueKeyApi/Program.cs | 1 + .../Services/CPMetaService.cs | 258 ++++++++++++++++++ 16 files changed, 518 insertions(+), 80 deletions(-) rename Projects/SystemX.Core/DB/SystemX.DB.CPMeta/dbo/{ => Tables}/tWbmsMeta.sql (59%) create mode 100644 Projects/WebApi/WebApi.Project.UniqueKeyApi/Controllers/CPMetaController.cs create mode 100644 Projects/WebApi/WebApi.Project.UniqueKeyApi/Services/CPMetaService.cs diff --git a/DBPatch/sqlScripts/SystemX.DB.CPMeta_Create.sql b/DBPatch/sqlScripts/SystemX.DB.CPMeta_Create.sql index 1ae9811..8b21993 100644 --- a/DBPatch/sqlScripts/SystemX.DB.CPMeta_Create.sql +++ b/DBPatch/sqlScripts/SystemX.DB.CPMeta_Create.sql @@ -248,14 +248,16 @@ PRINT N'테이블 [dbo].[tWbms]을(를) 만드는 중...'; GO CREATE TABLE [dbo].[tWbms] ( - [cProductID] NVARCHAR (50) NOT NULL, - [cMacAddress] NVARCHAR (50) NULL, - [cType] NVARCHAR (20) NULL, - [cProductNo] NVARCHAR (50) NULL, - [cSpareValue] NVARCHAR (200) NULL, - [cDateTime] DATETIME2 (7) NOT NULL, + [cProductID] NVARCHAR (50) NOT NULL, + [cMacAddress1] NVARCHAR (50) NULL, + [cMacAddress2] NVARCHAR (50) NULL, + [cType] NVARCHAR (20) NULL, + [cProductNo] NVARCHAR (50) NULL, + [cSpareValue] NVARCHAR (200) NULL, + [cDateTime] DATETIME2 (7) NOT NULL, CONSTRAINT [PK_cProductKey] PRIMARY KEY CLUSTERED ([cProductID] ASC), - CONSTRAINT [UQ_cMacAddress] UNIQUE NONCLUSTERED ([cMacAddress] ASC) + CONSTRAINT [UQ_cMacAddress1] UNIQUE NONCLUSTERED ([cMacAddress1] ASC), + CONSTRAINT [UQ_cMacAddress2] UNIQUE NONCLUSTERED ([cMacAddress2] ASC) ); diff --git a/DBPatch/sqlScripts/SystemX.DB.CPMeta_Update.sql b/DBPatch/sqlScripts/SystemX.DB.CPMeta_Update.sql index fc91ec7..173896d 100644 --- a/DBPatch/sqlScripts/SystemX.DB.CPMeta_Update.sql +++ b/DBPatch/sqlScripts/SystemX.DB.CPMeta_Update.sql @@ -43,19 +43,70 @@ USE [$(DatabaseName)]; GO /* -테이블 [dbo].[tWbmsMeta]의 열 [[dbo].[tWbmsMeta].[ctest]]을(를) 추가해야 하지만 해당 열에 기본값이 없으며 NULL 값을 허용하지 않습니다. 테이블에 데이터가 있으면 ALTER 스크립트가 실행되지 않습니다. 이러한 문제를 방지하려면 열에 기본값을 추가 및 해당 열을 NULL 값을 허용하도록 표시하거나 스마트 기본값을 배포 옵션으로서 생성할 수 있도록 하십시오. +[dbo].[tWbms].[cMacAddress] 열이 삭제되므로 데이터 손실이 발생할 수 있습니다. */ -IF EXISTS (select top 1 1 from [dbo].[tWbmsMeta]) +IF EXISTS (select top 1 1 from [dbo].[tWbms]) RAISERROR (N'행이 발견되었습니다. 데이터가 손실될 수 있으므로 스키마 업데이트가 종료됩니다.', 16, 127) WITH NOWAIT GO -PRINT N'테이블 [dbo].[tWbmsMeta]을(를) 변경하는 중...'; +PRINT N'UNIQUE 제약 조건 [dbo].[UQ_cMacAddress]을(를) 삭제하는 중...'; GO -ALTER TABLE [dbo].[tWbmsMeta] - ADD [ctest] DATETIME2 (7) NOT NULL; +ALTER TABLE [dbo].[tWbms] DROP CONSTRAINT [UQ_cMacAddress]; + + +GO +PRINT N'[dbo].[tWbms] 테이블 다시 빌드 시작...'; + + +GO +BEGIN TRANSACTION; + +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; + +SET XACT_ABORT ON; + +CREATE TABLE [dbo].[tmp_ms_xx_tWbms] ( + [cProductID] NVARCHAR (50) NOT NULL, + [cMacAddress1] NVARCHAR (50) NULL, + [cMacAddress2] NVARCHAR (50) NULL, + [cType] NVARCHAR (20) NULL, + [cProductNo] NVARCHAR (50) NULL, + [cSpareValue] NVARCHAR (200) NULL, + [cDateTime] DATETIME2 (7) NOT NULL, + CONSTRAINT [tmp_ms_xx_constraint_PK_cProductKey1] PRIMARY KEY CLUSTERED ([cProductID] ASC), + CONSTRAINT [tmp_ms_xx_constraint_UQ_cMacAddress11] UNIQUE NONCLUSTERED ([cMacAddress1] ASC), + CONSTRAINT [tmp_ms_xx_constraint_UQ_cMacAddress21] UNIQUE NONCLUSTERED ([cMacAddress2] ASC) +); + +IF EXISTS (SELECT TOP 1 1 + FROM [dbo].[tWbms]) + BEGIN + INSERT INTO [dbo].[tmp_ms_xx_tWbms] ([cProductID], [cType], [cProductNo], [cSpareValue], [cDateTime]) + SELECT [cProductID], + [cType], + [cProductNo], + [cSpareValue], + [cDateTime] + FROM [dbo].[tWbms] + ORDER BY [cProductID] ASC; + END + +DROP TABLE [dbo].[tWbms]; + +EXECUTE sp_rename N'[dbo].[tmp_ms_xx_tWbms]', N'tWbms'; + +EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_cProductKey1]', N'PK_cProductKey', N'OBJECT'; + +EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_UQ_cMacAddress11]', N'UQ_cMacAddress1', N'OBJECT'; + +EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_UQ_cMacAddress21]', N'UQ_cMacAddress2', N'OBJECT'; + +COMMIT TRANSACTION; + +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; GO diff --git a/DBPatch/sqlScripts/dacpac/SystemX.DB.CPMeta.dacpac b/DBPatch/sqlScripts/dacpac/SystemX.DB.CPMeta.dacpac index d3db354a187d89738047e585ced31a7a25cf5b5e..1380e4077686ebcbcf3dcc3e29e55374fda3ea5d 100644 GIT binary patch delta 2033 zcmY+Fc{me}AIFEe`OaCBBUicR%7&7AF;e8Lutvqm8MDYNXA(t|J3@}lw@v206+(`p za^;$G4vCrDukSyz&01zfFb|@fD3?#Mmk%BtNyhM z1ONi0Q@{}Xb?2ZlU6F|XemWkt->jXC4AFZf>5fQG14da4T6Jqw-~gE0-6`Lpbjp;R zMn<;q$Z6^*6eLz2PM+H7Pq}To6CnQPEkEJ{yJ5Ly$R}k02#(nK*=o5tT{HC>w1z(@ zvX#ra*TyA#7h-~nmFt;Cbj2@hSk?K67N6Ous=yySbSNcm$G`(nl0!y3r#Qy6=jdbs zt5G}t@dl4M%4RWobqC(IY37_Dej=)phm1-@L&y2h@v8}Yd%Tayp8(|2Vx5Jhcnx+( z7V7L$>j^K(mLLh(n^HPj%3NC3+_kV2&X?eZ0Tu=qYrp7S zki2|ZIA6vmrWGb>1N5L$U~f(aEG8(Loe%FRmCD|o-*!pQKHE{Tx^e znD{ODb1xH6aPbX&(mbiMd4oOcdjbw9^6rcqwchHhNp;G#JKp@5%c2Z19~A?9rq-7= zxF2!m;KEI(x3B!gqr*g&*FzGtUNr@NpEVkTM=H^q#P*L*GXvCc(MDxE1uF7Zisjb} zbAPrlyr&i3G46**?CNR9wdwN=a6eIk+x3mz3_V+QEwCcfAro*8=He+ZgX*&P)T$8` z-=5pxB_tXztv9v|xn&D3RgU`OX+r9Zl13D+#&xM7DdNiqzzxkI8>;cuXcmhMzx5o; zAIhW&d$suQwS_AMr-)JxI2kNgzvy}Cu^6mHWNc6PII=-S-k%^d&7ah6l6pLNXa(Z5 z!{v&ZaU8BAM%2Erp5@1SpSzm-Wv`CMt1c@BB>Z_oLq%Jqw_qH(4rRfg-GWx9mT*UR z-^R)tCjmcHjN>=7sUIVibiTxQs;mZbMLSf9u`qik{G)P=ZHD=8B?Caq)sO;T+vCgiOMW^yz1}0*g zYb#o+4Vi2}MJv`McPG4KMCVApMSByN_1h*}#Yk`2H46LSw9Ge?+P3!Ix2^_SnWE+@ zTftM7w8sU|I!wVtGuV+omVR?c6E0KU@~NX|jij zce@bD-P3YV2l-!0A)u{xlgE?hWG`*;!ULw9b~>B0U0>mqUTOTP{)5!6rIur_AEiPJ z93a*`IRTfXmEO&RK4xb&JV8HM3JbV2ZK|Kexm8~aU)gU>OC&$6TyCf7z&Ye(DURPL zFeg8}FZ#{H#XioNZcT2ITfB3$vg?F?DUx(3QHG2l?poVnDj;`t(7HRII^|`Ad1fcyX&a2BMx@7wtN(?bJkqm`8wr*CRobeU9FU zyq}Xv3uX6rTd12;=l6A>n3Us6YLh(@CUrS81Vy4looVJx4Yj%jhR?I&iRsW0bNtLC z!&QYxrrKqo$kATF+d-}1O5Ib$m3qyL9tEv<8>P4rsz9Ygt?41_9rXz?Rj)AKWz^ZnOG z_21hc3_OTiaB$mg8IEul+jV`9(;L>+8>GoMc!crYY~5DA>K+xBURljBg${L@BAa{J zJgctD4w$NK;cDBjf#JErWP$e3T(_M2esd754EB=;=S?q8882fVq(w$3Kup(+dsMOe zAMISLo;0KM656a>j)YLVrw6D0lbi&uZ-4!luY_Q3C00Zt8WU&GO zuD=<~^P9?lMwJ5qu)gc%>E)+(&)3K1A`7c3;19P~@`t9M{(h$Xmhd0b?=6F%$#a?` JnERjO{{ZJ)#r6OI delta 1992 zcmY+Fc{~%01BYj>ZMniSDQ)hMYpp3HM@mQ|OCqepk-15(xpGIE6uENEHPOl~@z$DR zvz5)Qh)|~7t;XB?$M1N*|9}5`KF_l$J0S}@XCo*i3jhE>fGXVOOCKrofN3EBfUA%L z(O9v zyuZ~v;t2{KTlz|2a2G83e79GcEpR9_dTR7}9acC3ZvOVvFKk&#cW2XN_phI%NTT<& z@Rd|r4k+G9;$Wf$Lb*)WV79<1zfYU(OW0V(R@O{kk?wgBW+`|u7v?+mkP>CCca3q_ zZ#g-i!L6%p`ywMuQE)rx?*n4hwkGJ8G5yp_5$$!{rP)1htA7TFX(`50xQ*JGFkZ}p$6rfhDYs^ zk{kB}IiaU_Kg7A;z)gK(K{1&TTe%n${dL_RZ93?i>DMM$U*yHil%Pzj0BMEqxd}8c zqV&{${W1a1IozkAM;hWxuMWa3j}ABGfRxOE8E1-zMpwmT^w<SsKC&hJN;&q=`po{Jd>V zg|A;_PAxPJfWk)Q388^$%M#Z+Jp@}ii~`3JlOG7Yz*Ujw5*xu5_w-_VZ8V)~tD7C$ zRPN1WHQ&jrh#dcZdtAxz!uL3DnMtVd9?jJoAxp(~J8i7u(1)dWVdx80V;5^y5bcXS zMgBpK{6J(0Re}2%F=g&UBZFzLcEiuu;4!nREZJQt%2`jdq|?^|7n&`0W?1&E27< z;y@t{Ti_iWfrGt89e!;6stX1jUlY6+FgH}s0s5>;apBr}`YnMa4BP9knUG$av;`Ye zhb<}=)2I$)>Y8KFa1N;)`ToaGI0nKRE|fM}7x`jtFSojde2Y*vQ%lSq zJfA}&4Vw(hwC#yWb*1=0%K2ZEn{x#f90$rV{cwUR{jXfwV)q_$TJGl(%{=vM)~#xH zb3bK>&g149lwHc&6 zo7{kZTTo{%#+U>E5FLbP!T(sXWNLFom3TtLjBpALwAw9IQ(Gl-&}TC%NLnin*<7Q> zf3Cx`=HD(5@^-w2h3@(swcPe)%XO?f_P4E~`=e1FwPL!=4*%JF40i|$4cM%iSSXSi z$sYN2)7osF@;PeKMP#t{!*TDJ0>RSxc$8(EILSey>AenA{G9G{9P61d^s&c)iaKiN zEa4eK0H!1cZ??Pe?hH0bv9Fk1VW?ko)bT;1b##~STVuHmcOdoUUB<~eaDda#NNER3 zExh2W5iUX|5RLxGb}?Xy4OlgsMzc{n`G>WiM->)*`URQnZFD?D7rznq#C!!$x_v%8 zd2(2^Rarw|6K`ESusA)Py6r5l)WDEeBEa70lM6N0aBosBF-H6?7W-jI0=Q!P-F7d} zAI~?dpzFPgPb{735$_GjoTG)9Bng^Q4|o`-G|G+0NmM^2bFUc7S{>i3A2SlC_pAC? zZB)ur(n7`BM!N#SceX+I4Q)ay>~O{dUe8`JYmDL6j>oJU*{F||7v>`ENLg$~5lAJ& zx0JK$?OF!MggZtg9&5(EQl?V7BLXTj9p}eH{TcdBJIGQ*q|-zGa#M+Oax5okijL}& z%v5yZ*go(Sb9Ps;#}B5a4>h!9na+M^3VTZZL^!v6zAtN@Km z{JW;aEbu{K6^_^j-Y1|+WP=rt{g*2s0O0ngxR5^${@2x&QzG diff --git a/Projects/Config/WebApi.Project.UniqueKeyApi.Config.json b/Projects/Config/WebApi.Project.UniqueKeyApi.Config.json index dcb8df7..6098926 100644 --- a/Projects/Config/WebApi.Project.UniqueKeyApi.Config.json +++ b/Projects/Config/WebApi.Project.UniqueKeyApi.Config.json @@ -13,18 +13,18 @@ { "IP": "127.0.0.1", "Port": 1433, - "DBName": "UniqueKeyDB", + "DBName": "CPMeta", "DBID": 1, - "UserID": "SystemX", - "Password": "X" + "UserID": "Alis", + "Password": "Kefico!@34" }, { "IP": "127.0.0.1", "Port": 1433, - "DBName": "UniqueKeyDB_DEV", + "DBName": "CPMeta_DEV", "DBID": 2, - "UserID": "SystemX", - "Password": "X" + "UserID": "Alis", + "Password": "Kefico!@34" } ] } \ No newline at end of file diff --git a/Projects/DLL/SystemX.Core.DB.dll b/Projects/DLL/SystemX.Core.DB.dll index 0c35936ae418fcffe728459272cee120b861744b..9575ca72eb6754b07bbfae66c45ab58d22928dc2 100644 GIT binary patch delta 24040 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 T*Gx&))*0p$?h3YRKWYCDCCs$b delta 23701 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 + - + xcopy /y $(ProjectDir)$(OutputPath)$(TargetName)_Create.sql $(SolutionDir)..\..\DBPatch\sqlScripts\ diff --git a/Projects/SystemX.Core/DB/SystemX.DB.CPMeta/dbo/tWbmsMeta.sql b/Projects/SystemX.Core/DB/SystemX.DB.CPMeta/dbo/Tables/tWbmsMeta.sql similarity index 59% rename from Projects/SystemX.Core/DB/SystemX.DB.CPMeta/dbo/tWbmsMeta.sql rename to Projects/SystemX.Core/DB/SystemX.DB.CPMeta/dbo/Tables/tWbmsMeta.sql index a4b2495..579ac79 100644 --- a/Projects/SystemX.Core/DB/SystemX.DB.CPMeta/dbo/tWbmsMeta.sql +++ b/Projects/SystemX.Core/DB/SystemX.DB.CPMeta/dbo/Tables/tWbmsMeta.sql @@ -1,7 +1,8 @@ CREATE TABLE [dbo].[tWbms] ( [cProductID] NVARCHAR(50) NOT NULL, - [cMacAddress] NVARCHAR(50) NULL, + [cMacAddress1] NVARCHAR(50) NULL, + [cMacAddress2] NVARCHAR(50) NULL, [cType] NVARCHAR(20) NULL, [cProductNo] NVARCHAR(50) NULL, @@ -9,5 +10,6 @@ [cDateTime] DATETIME2 NOT NULL, CONSTRAINT PK_cProductKey PRIMARY KEY (cProductID), - CONSTRAINT UQ_cMacAddress UNIQUE (cMacAddress), + CONSTRAINT UQ_cMacAddress1 UNIQUE (cMacAddress1), + CONSTRAINT UQ_cMacAddress2 UNIQUE (cMacAddress2), ) diff --git a/Projects/SystemX.Core/SystemX.Core.DB/CPMeta/Context/CPMetaContext.cs b/Projects/SystemX.Core/SystemX.Core.DB/CPMeta/Context/CPMetaContext.cs index f6d1941..8e62159 100644 --- a/Projects/SystemX.Core/SystemX.Core.DB/CPMeta/Context/CPMetaContext.cs +++ b/Projects/SystemX.Core/SystemX.Core.DB/CPMeta/Context/CPMetaContext.cs @@ -21,10 +21,13 @@ public partial class CPMetaContext : DbContext { entity.HasKey(e => e.cProductID).HasName("PK_cProductKey"); - entity.HasIndex(e => e.cMacAddress, "UQ_cMacAddress").IsUnique(); + entity.HasIndex(e => e.cMacAddress1, "UQ_cMacAddress1").IsUnique(); + + entity.HasIndex(e => e.cMacAddress2, "UQ_cMacAddress2").IsUnique(); entity.Property(e => e.cProductID).HasMaxLength(50); - entity.Property(e => e.cMacAddress).HasMaxLength(50); + entity.Property(e => e.cMacAddress1).HasMaxLength(50); + entity.Property(e => e.cMacAddress2).HasMaxLength(50); entity.Property(e => e.cProductNo).HasMaxLength(50); entity.Property(e => e.cSpareValue).HasMaxLength(200); entity.Property(e => e.cType).HasMaxLength(20); diff --git a/Projects/SystemX.Core/SystemX.Core.DB/CPMeta/Tables/tWbms.cs b/Projects/SystemX.Core/SystemX.Core.DB/CPMeta/Tables/tWbms.cs index 3264af9..7bbfba6 100644 --- a/Projects/SystemX.Core/SystemX.Core.DB/CPMeta/Tables/tWbms.cs +++ b/Projects/SystemX.Core/SystemX.Core.DB/CPMeta/Tables/tWbms.cs @@ -7,7 +7,9 @@ public partial class tWbms { public string cProductID { get; set; } = null!; - public string? cMacAddress { get; set; } + public string? cMacAddress1 { get; set; } + + public string? cMacAddress2 { get; set; } public string? cType { get; set; } diff --git a/Projects/WebApi/AuthApi/Services/AuthService.cs b/Projects/WebApi/AuthApi/Services/AuthService.cs index cabda8f..46f1a3a 100644 --- a/Projects/WebApi/AuthApi/Services/AuthService.cs +++ b/Projects/WebApi/AuthApi/Services/AuthService.cs @@ -264,7 +264,7 @@ namespace AuthApi.Services private AccountDBContext? GetAccountDBContext(DbContextProvider provider, int dbID) { var connectionString = _configService?.GetConfig()?.DataBase?.Find(x => x.DBID == dbID); - return provider?.GetDBContext($"{connectionString?.DBName}"); + return provider?.GetDBContext(Convert.ToInt32(connectionString?.DBID)); } } } diff --git a/Projects/WebApi/WebApi.Library/Enums/WebApiResult.cs b/Projects/WebApi/WebApi.Library/Enums/WebApiResult.cs index 876dc9f..4ee4887 100644 --- a/Projects/WebApi/WebApi.Library/Enums/WebApiResult.cs +++ b/Projects/WebApi/WebApi.Library/Enums/WebApiResult.cs @@ -10,5 +10,6 @@ namespace WebApi.Library.Enums { Success = 1, Failed = 2, + Update = 3, } } diff --git a/Projects/WebApi/WebApi.Project.UniqueKeyApi/Controllers/CPMetaController.cs b/Projects/WebApi/WebApi.Project.UniqueKeyApi/Controllers/CPMetaController.cs new file mode 100644 index 0000000..7ca580b --- /dev/null +++ b/Projects/WebApi/WebApi.Project.UniqueKeyApi/Controllers/CPMetaController.cs @@ -0,0 +1,70 @@ +using Microsoft.AspNetCore.Mvc; +using SystemX.Core.Controller; +using WebApi.Project.UniqueKeyApi.Models; +using WebApi.Project.UniqueKeyApi.Services; + +namespace WebApi.Project.UniqueKeyApi.Controllers +{ + [ApiController] + [Route("[controller]/[action]")] + + public class CPMetaController : CommonController + { + private readonly CPMetaService _cpMetaService; + + public CPMetaController(IServiceProvider serviceProvider, IHttpContextAccessor httpContextAccessor, CPMetaService cpMetaService) + : base(serviceProvider, httpContextAccessor) + { + _cpMetaService = cpMetaService; + } + + [HttpGet("health")] + public async Task Health() + { + LogXnet.WriteLine($"[{GetRequestMethod()}:{GetMethodName()}] [Client IP:{GetClientIP()}] [RequestUrl:{GetRequestUrl()}]{Environment.NewLine}", LogXLabel.CONTROLLER); + + await Task.CompletedTask; + return Results.Ok("Healthy"); + } + + + [HttpPost] + public async Task SetWbmsMeta([FromBody]Request_SetWbmsMeta request) + { + Guid guid = Guid.NewGuid(); + LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} {request.ToJson()}", LogXLabel.CONTROLLER); + + Response_SetWbmsMeta response = await _cpMetaService.SetWbmsMeta(request, guid.ToString()); + + LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); + + return Results.Ok(response); + } + + [HttpGet] + public async Task GetWbmsMetaByProductID([FromQuery] string ProductID, int? ShardID = 1) + { + Guid guid = Guid.NewGuid(); + LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} key:{ProductID}", LogXLabel.CONTROLLER); + + Response_GetWbms response = await _cpMetaService.GetWbmsMeta(new Request_GetWbmsMetaByProductID() { ProductID = ProductID, ShardID = (int)ShardID }, guid.ToString()); + + LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); + + return Results.Ok(response); + } + + [HttpGet] + public async Task GetWbmsMetaByMacAddress([FromQuery] string MacAddress, int? ShardID = 1) + { + Guid guid = Guid.NewGuid(); + LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} key:{MacAddress}", LogXLabel.CONTROLLER); + + Response_GetWbms response = await _cpMetaService.GetWbmsMeta(new Request_GetWbmsMetaByMacAddress() { MacAddress = MacAddress, ShardID = (int)ShardID }, guid.ToString()); + + LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); + + return Results.Ok(response); + } + } +} diff --git a/Projects/WebApi/WebApi.Project.UniqueKeyApi/Controllers/UniqueKeyController.cs b/Projects/WebApi/WebApi.Project.UniqueKeyApi/Controllers/UniqueKeyController.cs index d2929df..3193641 100644 --- a/Projects/WebApi/WebApi.Project.UniqueKeyApi/Controllers/UniqueKeyController.cs +++ b/Projects/WebApi/WebApi.Project.UniqueKeyApi/Controllers/UniqueKeyController.cs @@ -8,78 +8,78 @@ using WebApi.Project.UniqueKeyApi.Services; namespace WebApi.Project.UniqueKeyApi.Controllers { - [ApiController] - [Route("[controller]/[action]")] + //[ApiController] + //[Route("[controller]/[action]")] - public class UniqueKeyController : CommonController - { - private readonly UniqueKeyService _uniqueKeyService; + //public class UniqueKeyController : CommonController + //{ + // private readonly UniqueKeyService _uniqueKeyService; - public UniqueKeyController(IServiceProvider serviceProvider, IHttpContextAccessor httpContextAccessor, UniqueKeyService uniqueKeyService) - : base(serviceProvider, httpContextAccessor) - { - _uniqueKeyService = uniqueKeyService; - } + // public UniqueKeyController(IServiceProvider serviceProvider, IHttpContextAccessor httpContextAccessor, UniqueKeyService uniqueKeyService) + // : base(serviceProvider, httpContextAccessor) + // { + // _uniqueKeyService = uniqueKeyService; + // } - [HttpGet("health")] - public async Task Health() - { - LogXnet.WriteLine($"[{GetRequestMethod()}:{GetMethodName()}] [Client IP:{GetClientIP()}] [RequestUrl:{GetRequestUrl()}]{Environment.NewLine}", LogXLabel.CONTROLLER); + // [HttpGet("health")] + // public async Task Health() + // { + // LogXnet.WriteLine($"[{GetRequestMethod()}:{GetMethodName()}] [Client IP:{GetClientIP()}] [RequestUrl:{GetRequestUrl()}]{Environment.NewLine}", LogXLabel.CONTROLLER); - await Task.CompletedTask; - return Results.Ok("Healthy"); - } + // await Task.CompletedTask; + // return Results.Ok("Healthy"); + // } - [HttpPost] - public async Task InsertUniqueKey(Request_InsertUniqueKey request) - { - Guid guid = Guid.NewGuid(); - LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} {request.ToJson()}", LogXLabel.CONTROLLER); + // [HttpPost] + // public async Task InsertUniqueKey(Request_InsertUniqueKey request) + // { + // Guid guid = Guid.NewGuid(); + // LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} {request.ToJson()}", LogXLabel.CONTROLLER); - Response_InsertUniqueKy response = await _uniqueKeyService.Request_InsertUniqueKey(request); + // Response_InsertUniqueKy response = await _uniqueKeyService.Request_InsertUniqueKey(request); - LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); + // LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); - return Results.Ok(response); - } + // return Results.Ok(response); + // } - [HttpPost] - public async Task SelectUniqueKey([FromBody]Request_SelectUniqueKey request) - { - Guid guid = Guid.NewGuid(); - LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} {request.ToJson()}", LogXLabel.CONTROLLER); + // [HttpPost] + // public async Task SelectUniqueKey([FromBody]Request_SelectUniqueKey request) + // { + // Guid guid = Guid.NewGuid(); + // LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} {request.ToJson()}", LogXLabel.CONTROLLER); - Response_SelectUniqueKy response = await _uniqueKeyService.Request_SelectUniqueKey(request); + // Response_SelectUniqueKy response = await _uniqueKeyService.Request_SelectUniqueKey(request); - LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); + // LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); - return Results.Ok(response); - } + // return Results.Ok(response); + // } - [HttpGet] - public async Task SelectUniqueKeyGet([FromQuery] string key) - { - Guid guid = Guid.NewGuid(); - LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} key:{key}", LogXLabel.CONTROLLER); + // [HttpGet] + // public async Task SelectUniqueKeyGet([FromQuery] string key) + // { + // Guid guid = Guid.NewGuid(); + // LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} key:{key}", LogXLabel.CONTROLLER); - Response_SelectUniqueKy response = await _uniqueKeyService.Request_SelectUniqueKey(new Request_SelectUniqueKey { Identity = key }); + // Response_SelectUniqueKy response = await _uniqueKeyService.Request_SelectUniqueKey(new Request_SelectUniqueKey { Identity = key }); - LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); + // LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); - return Results.Ok(response); - } + // return Results.Ok(response); + // } - [HttpPost] - public async Task UpdateUniqueKey(Request_UpdateUniqueKey request) - { - Guid guid = Guid.NewGuid(); - LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} {request.ToJson()}", LogXLabel.CONTROLLER); + // [HttpPost] + // public async Task UpdateUniqueKey(Request_UpdateUniqueKey request) + // { + // Guid guid = Guid.NewGuid(); + // LogXnet.WriteLine($"[Request][{GetRequestMethod()}:{GetMethodName()}][Client IP:{GetClientIP()}][RequestUrl:{GetRequestUrl()}]::({guid}){Environment.NewLine} {request.ToJson()}", LogXLabel.CONTROLLER); - Response_UpdateUniqueKy response = await _uniqueKeyService.Request_UpdateUniqueKey(request); + // Response_UpdateUniqueKy response = await _uniqueKeyService.Request_UpdateUniqueKey(request); - LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); + // LogXnet.WriteLine($"[Response]::({guid}){Environment.NewLine} {response.ToJson()}", LogXLabel.CONTROLLER); - return Results.Ok(response); - } - } + // return Results.Ok(response); + // } + //} } diff --git a/Projects/WebApi/WebApi.Project.UniqueKeyApi/Models/Packet.cs b/Projects/WebApi/WebApi.Project.UniqueKeyApi/Models/Packet.cs index fe5af80..fbbebee 100644 --- a/Projects/WebApi/WebApi.Project.UniqueKeyApi/Models/Packet.cs +++ b/Projects/WebApi/WebApi.Project.UniqueKeyApi/Models/Packet.cs @@ -1,7 +1,54 @@ -using WebApi.Library.Enums; +using SystemX.Core.DB; +using WebApi.Library.Enums; namespace WebApi.Project.UniqueKeyApi.Models { + #region CPMeta Wbms + + //Wbms Meta Insert or Update + public class Request_SetWbmsMeta + { + //pk + public string ProductID { get; set; } = string.Empty; + //uk + public string? MacAddress1 { get; set; } = string.Empty; + public string? MacAddress2 { get; set; } = string.Empty; + + //value + public string? Type { get; set; } = string.Empty; + public string? ProductNo { get; set; } = string.Empty; + public string? SpareValue { get; set; } = string.Empty; + + public int ShardID { get; set; } = 1; + } + public class Response_SetWbmsMeta + { + public string ProductID { get; set; } = string.Empty; + public string Result { get; set; } = string.Empty; + public string Message { get; set; } = string.Empty; + } + + //Wbms Meta Select + public class Request_GetWbmsMetaByProductID + { + public string ProductID { get; set; } = string.Empty; + public int ShardID { get; set; } = 1; + } + public class Request_GetWbmsMetaByMacAddress + { + public string MacAddress { get; set; } = string.Empty; + public int ShardID { get; set; } = 1; + } + + public class Response_GetWbms + { + public List Wbms { get; set; } + public string Result { get; set; } = string.Empty; + public string Message { get; set; } = string.Empty; + } + + #endregion + #region Unique Key //Insert public class Request_InsertUniqueKey diff --git a/Projects/WebApi/WebApi.Project.UniqueKeyApi/Program.cs b/Projects/WebApi/WebApi.Project.UniqueKeyApi/Program.cs index 4e1b50c..28eb590 100644 --- a/Projects/WebApi/WebApi.Project.UniqueKeyApi/Program.cs +++ b/Projects/WebApi/WebApi.Project.UniqueKeyApi/Program.cs @@ -26,6 +26,7 @@ builder.Services.AddSingleton>(); //scoped builder.Services.AddSingleton(); +builder.Services.AddSingleton(); //db builder.Services.AddSingleton(); // Generic diff --git a/Projects/WebApi/WebApi.Project.UniqueKeyApi/Services/CPMetaService.cs b/Projects/WebApi/WebApi.Project.UniqueKeyApi/Services/CPMetaService.cs new file mode 100644 index 0000000..7ba3742 --- /dev/null +++ b/Projects/WebApi/WebApi.Project.UniqueKeyApi/Services/CPMetaService.cs @@ -0,0 +1,258 @@ +using Microsoft.EntityFrameworkCore; +using System.Data; +using SystemX.Core.DB; +using SystemX.Core.Services; +using WebApi.Library.Enums; +using WebApi.Project.UniqueKeyApi.Models; + +namespace WebApi.Project.UniqueKeyApi.Services +{ + public class CPMetaService + { + private readonly IServiceScopeFactory _scopeFactory; + private readonly ConfigService? _configService; + + public CPMetaService(IServiceProvider serviceProvider, IServiceScopeFactory scopeFactory, ConfigService configSerice) + { + _scopeFactory = scopeFactory; + _configService = configSerice; + } + + public async Task SetWbmsMeta(Request_SetWbmsMeta request, string guid = "") + { + Response_SetWbmsMeta response = new Response_SetWbmsMeta(); + + if (request != null) + { + response.ProductID = request.ProductID; + + bool transactionResult = true; + using (var scope = _scopeFactory.CreateScope()) + { + int shardId = request.ShardID; + if (shardId <= 0) + shardId = 1; + + var provider = scope.ServiceProvider.GetRequiredService(); + using (var context = GetCPMetaDBContext(provider, shardId)) + { + if (context is not null) + { + var data = await context.tWbms.AsNoTracking().Where(x => x.cProductID == request.ProductID)?.FirstOrDefaultAsync(); + if (data is not null) //update + { + var selected = await context.tWbms.FirstOrDefaultAsync(x => x.cProductID == request.ProductID); + if (selected != null) + { + selected.cMacAddress1 = request.MacAddress1; + selected.cMacAddress2 = request.MacAddress2; + selected.cType = request.Type; + selected.cProductNo = request.ProductNo; + selected.cSpareValue = request.SpareValue; + + selected.cDateTime = DateTime.Now; + + using (var transaction = await context.CreateTransactionAsync()) + { + context.Update(selected); + transactionResult = await context.CloseTransactionAsync(transaction); + } + } + + LogXnet.WriteLine($"Update::{guid}", LogXLabel.DB); + response.Result = WebApiResult.Update.ToString(); + } + else //insert + { + var row = new tWbms + { + cProductID = request.ProductID, + cMacAddress1 = request.MacAddress1, + cMacAddress2 = request.MacAddress2, + cType = request.Type, + cProductNo = request.ProductNo, + cSpareValue = request.SpareValue, + + cDateTime = DateTime.Now + }; + + using (var transaction = await context.CreateTransactionAsync()) + { + await context.AddAsync(row); + transactionResult = await context.CloseTransactionAsync(transaction); + } + + LogXnet.WriteLine($"Insert::{guid}", LogXLabel.DB); + response.Result = WebApiResult.Success.ToString(); + } + + //db error + if (transactionResult == false) + { + LogXnet.WriteLine($"Transaction Error::{guid}", LogXLabel.Error); + response.Result = WebApiResult.Failed.ToString(); + response.Message = "Duplicate Mac Address"; + } + } + else //invalid shard id + { + LogXnet.WriteLine($"ShardID Error::{guid}", LogXLabel.Error); + response.Result = WebApiResult.Failed.ToString(); + response.Message = "Invalid shard id"; + } + } + } + } + + return response; + } + + public async Task GetWbmsMeta(Request_GetWbmsMetaByProductID request, string guid = "") + { + Response_GetWbms response = new Response_GetWbms(); + response.Wbms = new List(); + + if (request != null) + { + using (var scope = _scopeFactory.CreateScope()) + { + int shardId = request.ShardID; + if (shardId <= 0) + shardId = 1; + + var provider = scope.ServiceProvider.GetRequiredService(); + using (var context = GetCPMetaDBContext(provider, shardId)) + { + if (context is not null) + { + try + { + using (var transaction = await context.CreateTransactionAsync(IsolationLevel.ReadUncommitted)) + { + var data = await context.tWbms.AsNoTracking().FirstOrDefaultAsync(x => x.cProductID.ToLower() == request.ProductID.ToLower()); + await context.CloseTransactionAsync(transaction); + if (data != null) + { + if(response.Wbms is not null) + { + response.Wbms.Add(data); + } + + response.Result = WebApiResult.Success.ToString(); + } + else + { + response.Wbms = null; + response.Result = WebApiResult.Failed.ToString(); + response.Message = $"Not exist productID: {request.ProductID}"; + } + } + } + catch (Exception e) + { + response.Wbms = null; + response.Result = WebApiResult.Failed.ToString(); + response.Message = $"Not exist productID: {request.ProductID}"; + + LogXnet.WriteLine($"GetWbmsMeta By ProductID Transaction Error::{guid}", LogXLabel.Error); + LogXnet.WriteLine(e); + } + } + else //invalid shard id + { + LogXnet.WriteLine($"ShardID Error::{guid}", LogXLabel.Error); + response.Result = WebApiResult.Failed.ToString(); + response.Message = "Invalid shard id"; + } + } + } + } + + return response; + } + + public async Task GetWbmsMeta(Request_GetWbmsMetaByMacAddress request, string guid = "") + { + Response_GetWbms response = new Response_GetWbms(); + response.Wbms = new List(); + + if (request != null) + { + using (var scope = _scopeFactory.CreateScope()) + { + int shardId = request.ShardID; + if (shardId <= 0) + shardId = 1; + + var provider = scope.ServiceProvider.GetRequiredService(); + using (var context = GetCPMetaDBContext(provider, shardId)) + { + if (context is not null) + { + try + { + using (var transaction = await context.CreateTransactionAsync(IsolationLevel.ReadUncommitted)) + { + var mac1 = await context.tWbms.AsNoTracking().FirstOrDefaultAsync(x => x.cMacAddress1.ToLower() == request.MacAddress.ToLower()); + var mac2 = await context.tWbms.AsNoTracking().FirstOrDefaultAsync(x => x.cMacAddress2.ToLower() == request.MacAddress.ToLower()); + await context.CloseTransactionAsync(transaction); + if (mac1 is not null) + { + if(response.Wbms is not null) + { + response.Wbms.Add(mac1); + } + response.Result = WebApiResult.Success.ToString(); + } + + if(mac2 is not null) + { + if (response.Wbms is not null) + { + response.Wbms.Add(mac2); + } + response.Result = WebApiResult.Success.ToString(); + } + + if(response.Wbms?.Count <= 0) + { + response.Wbms = null; + response.Result = WebApiResult.Failed.ToString(); + response.Message = $"Not exist MacAddress: {request.MacAddress}"; + } + } + } + catch (Exception e) + { + response.Wbms = null; + response.Result = WebApiResult.Failed.ToString(); + response.Message = $"Not exist MacAddrss: {request.MacAddress}"; + + LogXnet.WriteLine($"GetWbmsMeta By MacAddress Transaction Error::{guid}", LogXLabel.Error); + LogXnet.WriteLine(e); + } + } + else //invalid shard id + { + LogXnet.WriteLine($"ShardID Error::{guid}", LogXLabel.Error); + response.Result = WebApiResult.Failed.ToString(); + response.Message = "Invalid shard id"; + } + } + } + } + + return response; + } + + + private CPMetaContext? GetCPMetaDBContext(DbContextProvider provider, int dbID) + { + var connectionString = _configService?.GetConfig()?.DataBase?.Find(x => x.DBID == dbID); + if(connectionString is not null) + return provider?.GetDBContext((int)connectionString?.DBID); + + return null; + } + } +}