using System; using MySql.Data.MySqlClient; using FellowOakDicom; using FellowOakDicom.Network; using FellowOakDicom.Network.Client; using Microsoft.Extensions.Configuration; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection; namespace DicomMigratorApp { class Program { private static IConfiguration Configuration; private static ILogger _logger; private static string connectionString; private static string targetIP; private static string senderAET; private static string targetAET; private static string folderLocation; private static int targetPort; static async Task Main(string[] args) { var serviceProvider = new ServiceCollection() .AddLogging(config => { config.AddConsole(); config.SetMinimumLevel(LogLevel.Information); }) .BuildServiceProvider(); _logger = serviceProvider.GetService() .CreateLogger(); _logger.LogInformation("Application started"); connectionString = "Server=127.0.0.1;Port=3306;Database=dms_db;User Id=root;Password=Rootmatrix23@;"; targetIP = "127.0.0.1"; senderAET = "MYAE"; targetAET = "ORTHANC"; folderLocation = "D:\\dicom_imags\\"; var targetPortStr = "4242"; if (!int.TryParse(targetPortStr, out targetPort)) { _logger.LogError("TargetServer__Port environment variable is not a valid integer."); return; } try { var migrationStudy = await GetMigrationStudy(connectionString); if (migrationStudy == null) { _logger.LogInformation("No studies found for migration."); return; } _logger.LogInformation($"Retrieved studyDetails for Migration"); try { await MigrateStudy(migrationStudy.StudyInstanceUID, folderLocation + migrationStudy.StudyInstanceUID); await UpdateSourceCFind(connectionString, migrationStudy.StudyInstanceUID, "MIGRATION_COMPLETE"); } catch (DicomAssociationRejectedException ex) { _logger.LogError(ex, $"Association rejected for studyInstanceUID {migrationStudy.StudyInstanceUID}"); await UpdateSourceCFind(connectionString, migrationStudy.StudyInstanceUID, "MIGRATION_ERRORED"); } catch (Exception ex) { _logger.LogError(ex, $"An error occurred while retrieving or saving studyInstanceUID {migrationStudy.StudyInstanceUID}"); await UpdateSourceCFind(connectionString, migrationStudy.StudyInstanceUID, "MIGRATION_ERRORED"); } } catch (Exception ex) { _logger.LogError(ex, "An error occurred in the main processing loop"); } } private static async Task GetMigrationStudy(string connectionString) { var qrStudy = new SourceStudy(); try { using (var connection = new MySqlConnection(connectionString)) { _logger.LogInformation("Opening a connection to the database"); await connection.OpenAsync(); _logger.LogInformation("Database connection established"); var command = new MySqlCommand("SELECT study_instance_uid,patient_id,status FROM source_cfind WHERE status='QR_COMPLETE' LIMIT 1", connection); var reader = await command.ExecuteReaderAsync(); while (await reader.ReadAsync()) { qrStudy = new SourceStudy { StudyInstanceUID = reader.IsDBNull(0) ? null : reader.GetString(0), PatientID = reader.IsDBNull(1) ? null : reader.GetString(1), Status = reader.IsDBNull(2) ? null : reader.GetString(2) }; } reader.Close(); } if (qrStudy.StudyInstanceUID != null) { _logger.LogInformation("Picked study to be migrated from the database"); await UpdateSourceCFind(connectionString, qrStudy.StudyInstanceUID, "MIGRATION_INPROGRESS"); } else { qrStudy = null; } } catch (Exception ex) { _logger.LogError(ex, "Error retrieving study to be migrated from the database"); } return qrStudy; } private static async Task UpdateSourceCFind(string connectionString, string study_instance_uid, string updateStatus) { try { using (var connection = new MySqlConnection(connectionString)) { await connection.OpenAsync(); var command = new MySqlCommand("UPDATE source_cfind SET status = @Status WHERE study_instance_uid = @StudyInstanceUID", connection); command.Parameters.AddWithValue("@StudyInstanceUID", study_instance_uid); command.Parameters.AddWithValue("@Status", updateStatus); await command.ExecuteNonQueryAsync(); _logger.LogInformation($"Updated source C-FIND record for study instance uid {study_instance_uid}"); } } catch (Exception ex) { _logger.LogError(ex, $"Error updating source study record for study {study_instance_uid}"); } } private static async Task MigrateStudy(string studyInstanceUID, string folderPath) { var client = DicomClientFactory.Create(targetIP, targetPort, false, senderAET, targetAET); var files = System.IO.Directory.GetFiles(folderPath, "*"); foreach (var file in files) { var dicomFile = await DicomFile.OpenAsync(file); await client.AddRequestAsync(new DicomCStoreRequest(dicomFile)); } await client.SendAsync(); _logger.LogInformation($"Migrated studyInstanceUID {studyInstanceUID} to target AET {targetAET}"); } } class SourceStudy { public string PatientID { get; set; } public string StudyInstanceUID { get; set; } public string Status { get; set; } } }