Jira 2 Azure Devops migration tool in C#

I have been assigned a task to migrate Jira, our internal bug tracking system, to Azure DevOps cloud. There is a Jira plugin available, called TFS4JIAR, but it costs lots of money.

Here is my simple .Net C# code (if you want to use, you need modify to suit your own working environment)

Complete project can be found my github.

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace Jira2Azure
{
    class Program
    {
        static string JIRAIssueQuery = "http://jiraserver:8080/rest/api/latest/search?jql={0}&fields=*all";
        static string TFSBugUrl = "https://dev.azure.com/Test/SampleProject/_apis/wit/workitems/$Bug?api-version=6.0";
        static string TFSAttachmentUrl = "https://dev.azure.com/Test/SampleProject/_apis/wit/attachments?fileName={0}&api-version=6.0";

        static async Task<dynamic> JIRAGetIssues(string jql)
        {
            using (var client = new HttpClient())
            {
                //your Jira login credential
                client.DefaultRequestHeaders.Add("Authorization", "Basic XXXXXXXXXX");
                var msg = await client.GetStringAsync(string.Format(JIRAIssueQuery, jql));
                dynamic issues = JsonConvert.DeserializeObject(msg);
                return issues;
            }
        }

        static async Task JIRA2TFS(string jql)
        {
            var issues = await JIRAGetIssues(jql);
            foreach (var issue in issues.issues)
            {
                var tfs = ConvertJIRA2TFS(issue);
                await TFSCreateIssue(tfs);
            }
        }

        static async Task<dynamic> TFSUploadFile(string file, byte[] byteData)
        {
            file = Uri.EscapeUriString(file);
            using (var client = new HttpClient())
            {
                //your Azure login credential
                client.DefaultRequestHeaders.Add("Authorization", "Basic XXXXXXXXX");
                using (var content = new ByteArrayContent(byteData))
                {
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

                    var msg = await client.PostAsync(string.Format(TFSAttachmentUrl, file), content);
                    var responseBody = msg.Content.ReadAsStringAsync().Result;
                    return JsonConvert.DeserializeObject(responseBody);
                }
            }
        }
        static byte[] JIRADownloadFile(dynamic url)
        {
            using (var client = new HttpClient())
            {
                //your Jira login credential
                client.DefaultRequestHeaders.Add("Authorization", "Basic XXXXXXXX");
                var content = client.GetByteArrayAsync((string)url).Result;
                return content;
            }
        }
        static string ConvertJIRA2TFS(dynamic issue)
        {
            //Additional JIRA link for documentation
            string json = $"[{{\"op\": \"add\",\"path\": \"/relations/-\",\"value\": {{\"rel\": \"Hyperlink\",\"url\": \"{issue.self}\", \"attributes\": {{\"comment\": \"{issue.key}\"}}}}}},";
            if (issue.fields.attachment != null)
            {
                foreach (var attach in issue.fields.attachment)
                {
                    var content = JIRADownloadFile(attach.content);
                    var attchUrl = TFSUploadFile((string)attach.filename, content).Result;
                    var attachedJson = $"{{\"rel\":\"AttachedFile\",\"url\":\"{(string)attchUrl.url}\",\"attributes\":{{\"resourceSize\":{content.Length},\"name\":\"{(string)attach.filename}\"}}}}";
                    json += string.Format("{{\"op\":\"add\",\"path\":\"{0}\",\"from\": null,\"value\":{1}}},", "/relations/-", attachedJson);
                }
            }
            string operation = "{{\"op\":\"add\",\"path\":\"{0}\",\"from\": null,\"value\":\"{1}\"}},";
            //######### more field mapping
            var fieldMapping = new Dictionary<string, dynamic>()
            {
                { "/fields/System.Title",issue.fields.summary },
                { "/fields/Microsoft.VSTS.TCM.ReproSteps", issue.fields.description},
                { "/fields/Microsoft.VSTS.Common.Priority", issue.fields.priority.id},
            };

            foreach (var field in fieldMapping)
            {
                if (field.Value != null)
                {
                    var str = ((string)field.Value).Replace("\"", "\\\"");
                    json += string.Format(operation, field.Key, str);
                }
            }

            json = json.Replace("\r\n", "<br/>");
            json = json.TrimEnd(',');
            json += "]";
            return json;
        }

        static async Task TFSCreateIssue(string json)
        {
            using (var client = new HttpClient())
            {
                //your Azure login credential
                client.DefaultRequestHeaders.Add("Authorization", "Basic XXXXXXXXXX");
                var content = new StringContent(json, Encoding.UTF8, "application/json-patch+json");
                var msg = await client.PostAsync(TFSBugUrl, content);
            }
        }

        static async Task Main(string[] args)
        {
            await JIRA2TFS("project = TAP");
        }
    }
}

Connect a Java database via C# .Net

I am currently working on a software project that involves connecting to a Java database (Apache Derby) via a .Net C# application.  I googled a lot and nothing helps. Finally, I decided to find my own one, and managed to get it up running. Here is my solution to share:

Tools we need:

using java.lang;
using java.sql;
using System;
using org.apache.derby.jdbc;

namespace DerbyDB
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();

                DriverManager.registerDriver(new EmbeddedDriver());
                var derbyDBConnection = DriverManager.getConnection("jdbc:derby:C:/DerbyDB");
                if (derbyDBConnection != null)
                {
                    Statement st = derbyDBConnection.createStatement();
                    ResultSet rs = st.executeQuery("select * from eventlog");
                    while (rs.next())
                    {
                        Console.WriteLine(rs.getInt("ID"));
                        Console.WriteLine(rs.getTime("EVENT_DATE"));
                        Console.WriteLine(rs.getString("EVENT_MESSAGE"));
                    }
                    st.close();
                    derbyDBConnection.close();
                }
            }
            catch (java.lang.Exception e)
            {
                Console.WriteLine(e);
            }
        }
    }
}