using System; using Microsoft.Data.SqlClient; using System.Threading.Tasks; using leak_test_project.Models; namespace leak_test_project.Services { /// /// EOL 검사 데이터를 MSSQL 데이터베이스에 저장하는 서비스 클래스. /// public class EolDatabaseService { private readonly string _connectionString; public EolDatabaseService(string connectionString) { _connectionString = connectionString; } /// /// EOL 검사 결과를 데이터베이스에 저장합니다. (동일 ID 존재 시 업데이트, 미존재 시 삽입) /// /// 검사 결과 데이터 /// 저장 성공 여부 (성공: true, 실패: false) public async Task SaveEolDataAsync(InspectData inspectData, Housing.Login.StartupLoginWindowResult loginInfo) { if (inspectData == null) return false; // MSSQL MERGE 문을 사용한 UPSERT 처리 (신규 dbo.EOL 스키마 적용) const string query = @" MERGE INTO [dbo].[EOL] AS Target USING (SELECT @IC_SN AS IC_SN) AS Source ON (Target.IC_SN = Source.IC_SN) WHEN MATCHED THEN UPDATE SET Target.PCB_Barcode = @PCB_Barcode, Target.Maker = @Maker, Target.Model = @Model, Target.Variant_1 = @Variant_1, Target.Variant_2 = @Variant_2, Target.Operator = @Operator, Target.Production_Date = @Production_Date, Target.Line = @Line, Target.Lot_No = @Lot_No, Target.Jig_No = @Jig_No, Target.Channel = @Channel, Target.Spec_UL = @Spec_UL, Target.Spec_LL = @Spec_LL, Target.Leak_Value = @Leak_Value, Target.Result = @Result WHEN NOT MATCHED THEN INSERT (IC_SN, PCB_Barcode, Maker, Model, Variant_1, Variant_2, Operator, Production_Date, Line, Lot_No, Jig_No, Channel, Spec_UL, Spec_LL, Leak_Value, Result) VALUES (@IC_SN, @PCB_Barcode, @Maker, @Model, @Variant_1, @Variant_2, @Operator, @Production_Date, @Line, @Lot_No, @Jig_No, @Channel, @Spec_UL, @Spec_LL, @Leak_Value, @Result);"; try { var maker = loginInfo?.Maker ?? string.Empty; var model = loginInfo?.Model ?? string.Empty; var variant1 = loginInfo?.Variant1 ?? string.Empty; var variant2 = loginInfo?.Variant2 ?? string.Empty; var operatorId = loginInfo?.Operator ?? string.Empty; var lineNo = loginInfo?.LineNo ?? string.Empty; var lotNo = loginInfo?.LotNo ?? string.Empty; var jigNo = loginInfo?.JigNo ?? string.Empty; var builder = new SqlConnectionStringBuilder(_connectionString) { ConnectTimeout = 5 }; using (var conn = new SqlConnection(builder.ConnectionString)) { using (var cmd = new SqlCommand(query, conn)) { cmd.Parameters.AddWithValue("@IC_SN", string.IsNullOrEmpty(inspectData.IcSn) ? "-" : inspectData.IcSn); cmd.Parameters.AddWithValue("@PCB_Barcode", string.IsNullOrEmpty(inspectData.PcbBarcode) ? "-" : inspectData.PcbBarcode); cmd.Parameters.AddWithValue("@Maker", maker); cmd.Parameters.AddWithValue("@Model", model); cmd.Parameters.AddWithValue("@Variant_1", variant1); cmd.Parameters.AddWithValue("@Variant_2", variant2); cmd.Parameters.AddWithValue("@Operator", operatorId); cmd.Parameters.AddWithValue("@Production_Date", inspectData.ProductionDate ?? DateTime.Now); cmd.Parameters.AddWithValue("@Line", lineNo); cmd.Parameters.AddWithValue("@Lot_No", lotNo); cmd.Parameters.AddWithValue("@Jig_No", jigNo); cmd.Parameters.AddWithValue("@Channel", string.IsNullOrEmpty(inspectData.Channel) ? "N/A" : inspectData.Channel); // Spec_UL, Spec_LL, Leak_Value 형 변환 및 대입 decimal specUL = 0; if (decimal.TryParse(inspectData.SpecUL, out var parsedUL)) specUL = parsedUL; cmd.Parameters.AddWithValue("@Spec_UL", specUL); decimal specLL = 0; if (decimal.TryParse(inspectData.SpecLL, out var parsedLL)) specLL = parsedLL; cmd.Parameters.AddWithValue("@Spec_LL", specLL); decimal leakValue = 0; if (decimal.TryParse(inspectData.MeasuredValue, out var parsedValue)) leakValue = parsedValue; cmd.Parameters.AddWithValue("@Leak_Value", leakValue); cmd.Parameters.AddWithValue("@Result", string.IsNullOrEmpty(inspectData.Judgment) ? "NG" : inspectData.Judgment); await conn.OpenAsync(); await cmd.ExecuteNonQueryAsync(); Console.WriteLine($"[DB SUCCESS] EOL Data saved/updated for IC_SN: {inspectData.ProductId}"); return true; } } } catch (Exception ex) { // 실시간 검사 공정 루프 흐름이 DB 커넥션 예외로 중단되지 않도록 예외 격리 처리 Console.WriteLine($"[DB ERROR] Failed to upsert EOL Data: {ex.Message}"); throw; } } /// /// 데이터베이스 연결 상태를 비동기로 확인합니다. /// /// 연결 성공 시 true, 실패 시 false public async Task CheckConnectionAsync() { try { var builder = new SqlConnectionStringBuilder(_connectionString) { ConnectTimeout = 2 }; using (var conn = new SqlConnection(builder.ConnectionString)) { await conn.OpenAsync(); return true; } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"[DB Connection Check Error] {ex.Message}"); return false; } } /// /// dbo.Housing_Assembly 테이블에서 IC_SN을 기준으로 PCB_Barcode를 조회합니다. /// public async Task GetPcbBarcodeAsync(string icSn) { if (string.IsNullOrWhiteSpace(icSn)) return null; const string query = "SELECT [PCB_Barcode] FROM [dbo].[Housing_Assembly] WHERE [IC_SN] = @IC_SN"; var builder = new SqlConnectionStringBuilder(_connectionString) { ConnectTimeout = 5 }; using (var conn = new SqlConnection(builder.ConnectionString)) { using (var cmd = new SqlCommand(query, conn)) { cmd.Parameters.AddWithValue("@IC_SN", icSn); await conn.OpenAsync(); var result = await cmd.ExecuteScalarAsync(); if (result != null && result != DBNull.Value) { return result.ToString().Trim(); } } } return null; // 해당하는 매칭 데이터 없음 } } }