using System; using System.IO; using System.Collections.Generic; using System.Threading.Tasks; using Npgsql; using OpcPks.Core.Data; namespace OpcPks.Core.Data { public class AssetLoader { public async Task ImportFullMapAsync(string csvPath) { Console.WriteLine($"πŸš€ CSV 데이터 λ‘œλ“œ μ‹œμž‘: {csvPath}"); if (!File.Exists(csvPath)) { Console.WriteLine("❌ νŒŒμΌμ„ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."); return; } // CSV 파일 읽기 (첫 쀄 헀더 μ œμ™Έ) var lines = await File.ReadAllLinesAsync(csvPath); Console.WriteLine($"πŸ“Š 총 {lines.Length - 1}개의 라인을 μ²˜λ¦¬ν•©λ‹ˆλ‹€..."); using var conn = new NpgsqlConnection(DbConfig.ConnectionString); await conn.OpenAsync(); // PostgreSQL Binary Copy μ‹œμž‘ // level, class, name, node_id, data_type 총 5개 ν•„λ“œ using (var writer = conn.BeginBinaryImport("COPY raw_node_map (level, class, name, node_id, data_type) FROM STDIN (FORMAT BINARY)")) { int count = 0; for (int i = 1; i < lines.Length; i++) // i=1 λΆ€ν„° μ‹œμž‘ν•˜μ—¬ 헀더 μŠ€ν‚΅ { var line = lines[i]; if (string.IsNullOrWhiteSpace(line)) continue; var cols = line.Split(','); if (cols.Length < 4) continue; // μ΅œμ†Œ 4개 ν•„λ“œ(NodeIdκΉŒμ§€)λŠ” μžˆμ–΄μ•Ό 함 try { writer.StartRow(); // 1. Level (int) writer.Write(int.Parse(cols[0]), NpgsqlTypes.NpgsqlDbType.Integer); // 2. Class (string) writer.Write(cols[1], NpgsqlTypes.NpgsqlDbType.Text); // 3. Name (string) writer.Write(cols[2], NpgsqlTypes.NpgsqlDbType.Text); // 4. NodeId (string) writer.Write(cols[3], NpgsqlTypes.NpgsqlDbType.Text); // 5. DataType (데이터가 μ—†μœΌλ©΄ "Unknown" 처리) string dataType = cols.Length > 4 ? cols[4].Trim() : "Unknown"; writer.Write(dataType, NpgsqlTypes.NpgsqlDbType.Text); count++; if (count % 50000 == 0) Console.WriteLine($"... {count}개 처리 쀑"); } catch (Exception ex) { Console.WriteLine($"⚠️ μ—λŸ¬ λ°œμƒ (라인 {i+1}): {ex.Message}"); } } await writer.CompleteAsync(); Console.WriteLine($"βœ… 총 {count}개 λ…Έλ“œ λ‘œλ“œ μ™„λ£Œ!"); } } } }