using Microsoft.Office.Interop.Excel; using Npgsql; using System.Diagnostics; using Teigha.DatabaseServices; using Teigha.Runtime; using System.Collections.Generic; using System.IO; using System; namespace DwgExtractorManual.Models { /// /// DWG 파일에서 PostgreSQL 데이터베이스로 데이터 내보내기 클래스 /// AttributeReference, AttributeDefinition, DBText, MText 추출 지원 /// internal sealed class SqlDatas : IDisposable { Services appServices; // ODA 제품 활성화용 (managed by singleton) readonly string connectionString = "Host=localhost;Database=postgres;Username=postgres;Password=Qwer1234"; void InitializeTeighaServices() { try { Debug.WriteLine("[SqlDatas] TeighaServicesManager를 통한 Services 획득 중..."); appServices = TeighaServicesManager.Instance.AcquireServices(); Debug.WriteLine($"[SqlDatas] Services 획득 성공. Reference Count: {TeighaServicesManager.Instance.ReferenceCount}"); } catch (Teigha.Runtime.Exception ex) { Debug.WriteLine($"[SqlDatas] Teigha Services 초기화 실패: {ex.Message}"); throw; } } void CreateTables() { try { using (var conn = new NpgsqlConnection(connectionString)) { conn.Open(); // AttributeReferences 테이블 생성 (Title Block용) using (var cmd = new NpgsqlCommand()) { cmd.Connection = conn; cmd.CommandText = @" CREATE TABLE IF NOT EXISTS AttributeReferences ( Type VARCHAR(100), Name VARCHAR(255), Tag VARCHAR(255), Prompt VARCHAR(255), Value TEXT, Path TEXT, FileName TEXT, CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP )"; cmd.ExecuteNonQuery(); } // TextEntities 테이블 생성 (DBText/MText용) using (var cmd = new NpgsqlCommand()) { cmd.Connection = conn; cmd.CommandText = @" CREATE TABLE IF NOT EXISTS TextEntities ( Type VARCHAR(50), Layer VARCHAR(255), Text TEXT, Path TEXT, FileName TEXT, CreatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP )"; cmd.ExecuteNonQuery(); } } } catch (System.Exception ex) { Debug.WriteLine($"테이블 생성 중 오류: {ex.Message}"); throw; } } public SqlDatas() { InitializeTeighaServices(); CreateTables(); } /// /// DWG 파일 데이터를 데이터베이스에 저장 /// /// DWG 파일 경로 /// 실패시 true, 성공시 false (기존 콘솔 버전과 호환성) public bool DwgToDB(string filePath) { var result = false; using (var database = new Database(false, true)) { try { database.ReadDwgFile(filePath, FileOpenMode.OpenForReadAndWriteNoShare, false, null); using (var conn = new NpgsqlConnection(connectionString)) { conn.Open(); using (var tran = database.TransactionManager.StartTransaction()) { // Document Information 추출 DatabaseSummaryInfo summaryInfo = database.SummaryInfo; string documentInfo = $"Title: {summaryInfo.Title}, Subject: {summaryInfo.Subject}, Author: {summaryInfo.Author}"; Dictionary dicTagPrompt = new Dictionary(); // Block Table 접근 var bt = tran.GetObject(database.BlockTableId, OpenMode.ForRead) as BlockTable; using (var btr = tran.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord) { foreach (ObjectId entId in btr) { using (var ent = tran.GetObject(entId, OpenMode.ForRead) as Entity) { // Layer 이름 가져오기 (공통) string layerName = GetLayerName(ent.LayerId, tran, database); // AttributeDefinition 처리는 생략 (필요시 추가) if (ent is AttributeDefinition attDef) { // 현재는 AttributeDefinition 처리하지 않음 } // DBText 엔티티 처리 (별도 테이블) else if (ent is DBText dbText) { using (var cmd = new NpgsqlCommand()) { cmd.Connection = conn; cmd.CommandText = @" INSERT INTO TextEntities (Type, Layer, Text, Path, FileName) VALUES (@Type, @Layer, @Text, @Path, @FileName)"; cmd.Parameters.AddWithValue("Type", "DBText"); cmd.Parameters.AddWithValue("Layer", layerName); cmd.Parameters.AddWithValue("Text", dbText.TextString ?? ""); cmd.Parameters.AddWithValue("Path", database.Filename); cmd.Parameters.AddWithValue("FileName", Path.GetFileName(database.Filename)); cmd.ExecuteNonQuery(); } } // MText 엔티티 처리 (별도 테이블) else if (ent is MText mText) { using (var cmd = new NpgsqlCommand()) { cmd.Connection = conn; cmd.CommandText = @" INSERT INTO TextEntities (Type, Layer, Text, Path, FileName) VALUES (@Type, @Layer, @Text, @Path, @FileName)"; cmd.Parameters.AddWithValue("Type", "MText"); cmd.Parameters.AddWithValue("Layer", layerName); cmd.Parameters.AddWithValue("Text", mText.Contents ?? ""); cmd.Parameters.AddWithValue("Path", database.Filename); cmd.Parameters.AddWithValue("FileName", Path.GetFileName(database.Filename)); cmd.ExecuteNonQuery(); } } else if (ent is BlockReference blr) { foreach (ObjectId attId in blr.AttributeCollection) { using (var attRef = tran.GetObject(attId, OpenMode.ForRead) as AttributeReference) { using (var cmd = new NpgsqlCommand()) { cmd.Connection = conn; cmd.CommandText = @" INSERT INTO AttributeReferences (Type, Name, Tag, Prompt, Value, Path, FileName) VALUES (@Type, @Name, @Tag, @Prompt, @Value, @Path, @FileName)"; var typeFullName = attRef.GetType().ToString(); var typeName = typeFullName.Substring(typeFullName.LastIndexOf('.') + 1); var blkName = blr.Name; var attTag = attRef.Tag; string prompt = ""; string tString = ""; if (!bt.Has(blkName)) { continue; } if (dicTagPrompt.ContainsKey(attTag)) { prompt = dicTagPrompt[attTag]; } else { // 블록 정의 찾기 ObjectId blockDefId = bt[blkName]; BlockTableRecord blkDef = (BlockTableRecord)tran.GetObject(blockDefId, OpenMode.ForRead); // AttributeDefinition 순회 및 태그 일치 확인 foreach (ObjectId objId in blkDef) { DBObject dbObj = tran.GetObject(objId, OpenMode.ForRead); if (dbObj is AttributeDefinition adef) { if (adef.Tag.ToUpper() == attTag.ToUpper()) { prompt = adef.Prompt; dicTagPrompt.Add(attTag, prompt); tString = adef.TextString; break; } } } } cmd.Parameters.AddWithValue("Type", typeName); cmd.Parameters.AddWithValue("Name", blr.Name); cmd.Parameters.AddWithValue("Tag", attTag); cmd.Parameters.AddWithValue("Prompt", prompt); if (!string.IsNullOrEmpty(attRef.TextString)) cmd.Parameters.AddWithValue("Value", attRef.TextString); else cmd.Parameters.AddWithValue("Value", tString); cmd.Parameters.AddWithValue("Path", database.Filename); cmd.Parameters.AddWithValue("FileName", Path.GetFileName(database.Filename)); cmd.ExecuteNonQuery(); } } } } } } } tran.Commit(); } } } catch (System.Exception ex) { result = true; // 실패시 true 반환 (기존 버전과 호환성) Debug.WriteLine($"DWG 파일 처리 중 오류: {ex.Message}"); } } return result; } /// /// 데이터베이스 연결 테스트 /// /// 연결 성공 여부 public bool TestConnection() { try { using (var conn = new NpgsqlConnection(connectionString)) { conn.Open(); return true; } } catch (System.Exception ex) { Debug.WriteLine($"데이터베이스 연결 테스트 실패: {ex.Message}"); return false; } } /// /// Layer ID로부터 Layer 이름을 가져옵니다. /// /// Layer ObjectId /// 현재 트랜잭션 /// 데이터베이스 객체 /// Layer 이름 또는 빈 문자열 private string GetLayerName(ObjectId layerId, Transaction transaction, Database database) { try { using (var layerTableRecord = transaction.GetObject(layerId, OpenMode.ForRead) as LayerTableRecord) { return layerTableRecord?.Name ?? ""; } } catch (System.Exception ex) { Debug.WriteLine($"Layer 이름 가져오기 오류: {ex.Message}"); return ""; } } /// /// 리소스 해제 /// public void Dispose() { if (appServices != null) { try { Debug.WriteLine("[SqlDatas] Teigha Services 해제 중..."); TeighaServicesManager.Instance.ReleaseServices(); Debug.WriteLine($"[SqlDatas] Teigha Services 해제 완료. Remaining ref count: {TeighaServicesManager.Instance.ReferenceCount}"); } catch (Teigha.Runtime.Exception ex) { Debug.WriteLine($"[SqlDatas] Teigha Services 해제 중 오류 (무시됨): {ex.Message}"); } finally { appServices = null; } } } } }