Apache log4net™ กับ .NET 6 BlazorServer

สร้างโปรเจ็กส์แบบ Blazor Server App

1. ทดสอบ logger

ที่ไฟล์ Pages/Counter.razor เพิ่มโค๊ด _logger.* ไว้ดูผลการ log

@page "/counter"
@inject ILogger<Counter> logger

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        logger.LogInformation("This is an INFORMATION message.");
        logger.LogWarning("This is a WARNING message.");
        logger.LogError("This is an ERROR message.");

        currentCount++;
    }
}

เปิดหน้าต่าง Output โดยไปที่เมนู View | Output

ทดลองเรียกไปที่หน้า Counter เช่น https://localhost:7180/counter แล้วดูที่หน้าต่าง Output

BlazorServerApp6.Pages.Counter: Information: This is an INFORMATION message.
BlazorServerApp6.Pages.Counter: Warning: This is a WARNING message.
BlazorServerApp6.Pages.Counter: Error: This is an ERROR message.

2. ใช้ log4net

ติดตั้ง Package log4net และ Microsoft.Extensions.Logging.Log4Net.AspNetCore

PM> NuGet\Install-Package log4net -Version 2.0.15
PM> NuGet\Install-Package Microsoft.Extensions.Logging.Log4Net.AspNetCore -Version 6.1.0

สร้างไฟล์ log4net.config

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
    <file value="log/" />
    <datePattern value="yyMMdd'Jack.log'" />
    <staticLogFileName value="false"/>
    <appendToFile value="true"/>
    <rollingStyle value="Date"/>
    <maxSizeRollBackups value="100"/>
    <maximumFileSize value="15MB"/>
    <encoding value="UTF-8"/>
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="%-5p%d{ HH:mm:ss} li:%line - [%method] %m  %n" />
    </layout>
  </appender>
  <root>
    <level value="ALL"/>
    <appender-ref ref="RollingLogFileAppender"/>
  </root>
</log4net>

แก้ไขไฟล์ Program.cs

using BlazorServerApp6.Data;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

var builder = WebApplication.CreateBuilder(args);

ILoggerFactory _loggerFactory = (ILoggerFactory)new LoggerFactory();
_loggerFactory.AddLog4Net();
builder.Services.AddSingleton(_loggerFactory);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

ทดลองเรียกหน้า Counter อีกครั้งจะได้ไฟล์ .log

Posted in C#

Apache log4net™ กับ .NET 6 WebMVC

สร้างโปรเจ็กส์แบบ ASP.NET Core Web App (Model-View-Controller)

1. ทดสอบ logger

ที่ไฟล์ Controllers/HomeController.cs เพิ่มโค๊ด _logger.* ไว้ดูผลการ log

using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
using WebMvc6.Models;

namespace WebMvc6.Controllers
{
    public class HomeController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        public IActionResult Index()
        {
            _logger.LogInformation("This is an INFORMATION message.");
            _logger.LogWarning("This is a WARNING message.");
            _logger.LogError("This is an ERROR message.");

            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

เปิดหน้าต่าง Output โดยไปที่เมนู View | Output

ทดลองเรียกไปที่หน้า Home เช่น https://localhost:7138/ แล้วดูที่หน้าต่าง Output

WebMvc6.Controllers.HomeController: Information: This is an INFORMATION message.
WebMvc6.Controllers.HomeController: Warning: This is a WARNING message.
WebMvc6.Controllers.HomeController: Error: This is an ERROR message.

2. ใช้ log4net

ติดตั้ง Package log4net และ Microsoft.Extensions.Logging.Log4Net.AspNetCore

PM> NuGet\Install-Package log4net -Version 2.0.15
PM> NuGet\Install-Package Microsoft.Extensions.Logging.Log4Net.AspNetCore -Version 6.1.0

สร้างไฟล์ log4net.config

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
    <file value="log/" />
    <datePattern value="yyMMdd'Jack.log'" />
    <staticLogFileName value="false"/>
    <appendToFile value="true"/>
    <rollingStyle value="Date"/>
    <maxSizeRollBackups value="100"/>
    <maximumFileSize value="15MB"/>
    <encoding value="UTF-8"/>
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="%-5p%d{ HH:mm:ss} li:%line - [%method] %m  %n" />
    </layout>
  </appender>
  <root>
    <level value="ALL"/>
    <appender-ref ref="RollingLogFileAppender"/>
  </root>
</log4net>

แก้ไขไฟล์ Program.cs

var builder = WebApplication.CreateBuilder(args);

ILoggerFactory _loggerFactory = (ILoggerFactory)new LoggerFactory();
_loggerFactory.AddLog4Net();
builder.Services.AddSingleton(_loggerFactory);

// Add services to the container.
builder.Services.AddControllersWithViews();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

ทดลองเรียกหน้า Home อีกครั้งจะได้ไฟล์ .log

Posted in C#

Apache log4net™ กับ .NET 6 WebApp

สร้างโปรเจ็กส์แบบ ASP.NET Core Web App

1. ทดสอบ logger

ที่ไฟล์ Pages/Index.cshtml.cs เพิ่มโค๊ด _logger.* ไว้ดูผลการ log

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace WebApp6.Pages
{
    public class IndexModel : PageModel
    {
        private readonly ILogger<IndexModel> _logger;

        public IndexModel(ILogger<IndexModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
            _logger.LogInformation("This is an INFORMATION message.");
            _logger.LogWarning("This is a WARNING message.");
            _logger.LogError("This is an ERROR message.");
        }
    }
}

เปิดหน้าต่าง Output โดยไปที่เมนู View | Output

ทดลองเรียกไปที่หน้า Home เช่น https://localhost:7138/ แล้วดูที่หน้าต่าง Output

WebApp6.Pages.IndexModel: Information: This is an INFORMATION message.
WebApp6.Pages.IndexModel: Warning: This is a WARNING message.
WebApp6.Pages.IndexModel: Error: This is an ERROR message.

2. ใช้ log4net

ติดตั้ง Package log4net และ Microsoft.Extensions.Logging.Log4Net.AspNetCore

PM> NuGet\Install-Package log4net -Version 2.0.15
PM> NuGet\Install-Package Microsoft.Extensions.Logging.Log4Net.AspNetCore -Version 6.1.0

สร้างไฟล์ log4net.config

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
    <file value="log/" />
    <datePattern value="yyMMdd'Jack.log'" />
    <staticLogFileName value="false"/>
    <appendToFile value="true"/>
    <rollingStyle value="Date"/>
    <maxSizeRollBackups value="100"/>
    <maximumFileSize value="15MB"/>
    <encoding value="UTF-8"/>
    <layout type="log4net.Layout.PatternLayout">
      <param name="ConversionPattern" value="%-5p%d{ HH:mm:ss} li:%line - [%method] %m  %n" />
    </layout>
  </appender>
  <root>
    <level value="ALL"/>
    <appender-ref ref="RollingLogFileAppender"/>
  </root>
</log4net>

แก้ไขไฟล์ Program.cs

var builder = WebApplication.CreateBuilder(args);

ILoggerFactory _loggerFactory = (ILoggerFactory)new LoggerFactory();
_loggerFactory.AddLog4Net();
builder.Services.AddSingleton(_loggerFactory);

// Add services to the container.
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

ทดลองเรียกหน้า Home อีกครั้งจะได้ไฟล์ .log

Posted in C#

WebApp ที่ Authorization ด้วย Bearer Token

1.สร้าง WebApp

สร้างโปรเจ็กส์แบบ ASP.NET Web Application ชื่อ WebApp1

เลือก template แบบ Web API

2.แก้ไข routeTemplate

เดิม routeTemplate จะมีค่าเป็น "api/{controller}/{id}" ถ้าต้องการปรับ routeTemplate สามารถปรับได้ที่ไฟล์ App_start/WebApiConfig.cs

เช่นถ้าต้องการให้มี 2 GET Method ใน controller เดียวกัน ให้แยกด้วย action

routeTemplate: "{controller}/{action}/{id}",

และแก้ไขที่ controller

// GET mycontroller/getName
[HttpGet]
[ActionName("getName")]
public string getName([FromBody]myReq1 req) 
{}

// GET mycontroller/getId
[HttpGet]
[ActionName("getId")]
public string getId([FromBody]myReq2 req)
{}

3.รับ Authorization ด้วย Bearer Token

รับ Authorization ด้วย Bearer Token แบบ short string of hexadecimal characters

ตัวอย่างโค๊ดจาก Action Request Token Verification C# Sample

// POST api/values
public void Post([FromBody]string value)
{
    try
    {
        HttpRequestMessage request = Request;

        // Validate that we have a bearer token.
        if (request.Headers.Authorization == null ||
            !string.Equals(request.Headers.Authorization.Scheme, "bearer", StringComparison.OrdinalIgnoreCase) ||
            string.IsNullOrEmpty(request.Headers.Authorization.Parameter))
        {
            log.Error("missing bearer token");
            return;
        }

        // Get the token from the Authorization header 
        string bearerToken = request.Headers.Authorization.Parameter;
        log.Info(string.Format("bearerToken [{0}]", bearerToken));
    }
    catch (Exception ex)
    {
        log.Error(ex.Message);
        log.Error(ex.ToString());
    }
}

ตัวอย่งการเรียก request ด้วย Postman

Posted in C#

การ split ไฟล์ PDF ด้วย iTextSharp

ติดตั้ง

PM> Install-Package iTextSharp -Version 5.5.13.2

หน้าแรกของ PDF คือหน้าที่ 1

using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Reflection;

namespace ConsoleApp1
{
    class Program
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        static void Main(string[] args)
        {
            try
            {
                log.Info("*********************************");
                log.Info("************* BEGIN *************");
                log.Info(AppDomain.CurrentDomain.FriendlyName);

                string sourcePDFpath = "iptest.pdf";
                string outputPDFpath = "optest.pdf";
                int startpage = 1;
                int endpage = 1;
                ExtractPages(sourcePDFpath, outputPDFpath, startpage, endpage);

                log.Info("************** END **************");
                log.Info("");
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
                log.Error(ex.ToString());
            }
        } // end main

        private static void ExtractPages(string sourcePDFpath, string outputPDFpath, int startpage, int endpage)
        {
            PdfReader reader = null;
            Document sourceDocument = null;
            PdfCopy pdfCopyProvider = null;
            PdfImportedPage importedPage = null;

            reader = new PdfReader(sourcePDFpath);
            sourceDocument = new Document(reader.GetPageSizeWithRotation(startpage));
            pdfCopyProvider = new PdfCopy(sourceDocument, new System.IO.FileStream(outputPDFpath, System.IO.FileMode.Create));

            sourceDocument.Open();

            for (int i = startpage; i <= endpage; i++)
            {
                importedPage = pdfCopyProvider.GetImportedPage(reader, i);
                pdfCopyProvider.AddPage(importedPage);
            }
            sourceDocument.Close();
            reader.Close();
        }
    } // end class
}

การเรียก POST ด้วย HttpWebRequest

ถ้าเรียก HttpWebRequest แล้วเจอ error

The request was aborted: Could not create SSL/TLS secure channel.  

[Main] System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
   at System.Net.HttpWebRequest.GetResponse()

ให้แก้ไขด้วยการวาง ServicePointManager

ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// SecurityProtocolType.Tls
// SecurityProtocolType.Tls11
// SecurityProtocolType.Ssl3;

ไว้ก่อน HttpWebRequest

//createing HttpWebRequest after ServicePointManager settings
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")

ตัวอย่าง

ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
// ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11
// ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://example.com/api/")
request.ContentType = "application/json";
request.Method = "POST";

using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
    People movReq = new People();

    People.username = "user1";
    People.password = "paas1";
    People.xxx = "xxx";
    
    string jsonReq = JsonConvert.SerializeObject(movReq);
    log.Info(string.Format("Request: jsonString='{0}'", jsonReq));

    streamWriter.Write(jsonReq);
}

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
MOVRealTimeResponse resp;
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
    var result = streamReader.ReadToEnd();
    log.Info(string.Format("Response: string='{0}'", result));

    resp = JsonConvert.DeserializeObject<MOVRealTimeResponse>(result);
}
Posted in C#

การแปลงข้อความให้เป็นเสียงพูด (Text to Speech: TTS) บน Windows 10

1.ตรวจสอบเสียงที่ติดตั้งมาในเครื่อง

เปิด Control Panel แล้วเลือก Speech Recognition

เลือก Text to Speech

ที่หน้าต่าง Speech Properties จะแสดงเสียงที่ติดตั้งอยู่ในเครื่อง

2.เขียน C# ด้วย .Net Framework 4.8

สร้างโปรเจ็กส์แบบ Console

Add Reference ชื่อ System.Speech Version 4.0.0.0

เพิ่มโค๊ด C#

using System.Speech.Synthesis;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            SpeechSynthesizer syn = new SpeechSynthesizer();
            syn.Speak("I love Thailand.");
        }
    }
}

เมื่อรันจะได้ยินเสียงละ

เปลี่ยนเสียงพูดเป็นของ Microsoft Zira Desktop

using System.Speech.Synthesis;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            SpeechSynthesizer syn = new SpeechSynthesizer();
            syn.SelectVoice("Microsoft Zira Desktop");
            syn.Speak("I love Thailand.");
        }
    }
}

ปรับความเร็วของเสียงพูด ค่าบวกยิ่งมากยิ่งพูดเร็ว ค่าลบยิ่งลดมากยิ่งพูดช้า

using System.Speech.Synthesis;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            SpeechSynthesizer syn = new SpeechSynthesizer();
            syn.SelectVoice("Microsoft Zira Desktop");
            syn.Rate = 1;  // -10 to 10
            syn.Speak("I love Thailand.");
        }
    }
}

Posted in C#

ตรวจสอบเลขบัตรประชาชน

ตัวอย่าง 1-2345-67890-12-1

  1. นำไปคูณเลขประจำตำแหน่ง : (1*13)+(2*12)+(3*11)+(4*10)+(5*9)+(6*8)+(7*7)+(8*6)+(9*5)+(0*4)+(1*3)+(2*2) = 352
  2. หารเอาเศษด้วย : 11 352%11= 0
  3. นำ 11 ตั้งแล้วลบเศษที่ได้จากการหารในข้อ 2 : 11 – 0 = 11 (เอาเลขหลักหน่วย) ดังนั้น Check Digit คือ 1
  4. จะได้ : 1-2345-67890-12-1
private static bool validateIDCard(string idcardno)
{
    if (string.IsNullOrEmpty(idcardno))
    {
        log.Info(string.Format("idcardno IsNullOrEmpty '{0}'", idcardno));
        return false;
    }

    if (idcardno.Length != 13)
    {
        log.Info(string.Format("idcardno Length != 13 '{0}'", idcardno));
        return false;
    }

    bool isDigit = Regex.IsMatch(idcardno, @"^[0-9]*$");
    if (!isDigit)
    {
        log.Info(string.Format("idcardno is not only digit '{0}'", idcardno));
        return false;
    }


    int sum = 0;
    for (int i = 0; i < 12; i++)
    {
        sum += Convert.ToInt32(idcardno.Substring(i, 1)) * (13 - i);
    }

    int checksum = (11 - (sum % 11)) % 10;
    if (checksum != Convert.ToInt32(idcardno.Substring(12)))
    {
        log.Info(string.Format("idcardno checksum error '{0}', sum = '{1}', checksum = '{2}'", idcardno, sum, checksum));
        return false;
    }

    return true;
}
Posted in C#

Console เชื่อมต่อ MySQL

  1. ติดตั้ง MySql.Data ผ่าน NuGet
  2. สร้างโฟลเดอร์ mysql
  3. สร้างคลาส mysql/sql.cs
  4. สร้างคลาส mysql/qry.cs
  5. แก้ไขไฟล์ App.config
  6. แก้ไขไฟล์ Program.cs

1.ติดตั้ง MySql.Data ผ่าน NuGet

PM> Install-Package MySql.Data -Version 6.9.12

2.สร้างโฟลเดอร์ mysql

3.สร้างคลาส mysql/sql.cs

using MySql.Data.MySqlClient;
using System;
using System.Configuration;
using System.Data;
using System.Reflection;
using System.Text.RegularExpressions;

namespace ConsoleApp1.mysql
{
    class sql
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        private static string connMySql = ConfigurationManager.AppSettings.Get("connMySql");


        public static DataTable ExecuteQuery(string query)
        {
            query = Regex.Replace(query, @"\s+", " ");
            log.Debug(query);

            try
            {
                using (MySqlConnection conn = new MySqlConnection(connMySql))
                {
                    conn.Open();
                    MySqlDataAdapter da = new MySqlDataAdapter(query, conn);
                    System.Data.DataSet ds = new System.Data.DataSet("Names");
                    da.Fill(ds);
                    DataTable dt = ds.Tables[0];

                    conn.Close();

                    log.Debug(string.Format("  found {0} record.", dt.Rows.Count));
                    return dt;
                }
            }
            catch (MySqlException ex)
            {
                log.Error(ex.Message);
                return null;
            }
        }

        public static DataTable ExecuteReader(string query)
        {
            //log.Info(string.Format("  '{0}'", connIIA.Split(';')[0]));

            query = Regex.Replace(query, @"\s+", " ");
            log.Debug(query);

            DataSet ds;
            try
            {
                // Open a connection
                using (MySqlConnection conn = new MySqlConnection(connMySql))
                {
                    conn.Open();
                    using (MySqlTransaction trans = conn.BeginTransaction(IsolationLevel.ReadUncommitted))
                    {
                        // Create an SQL command
                        using (MySqlCommand cmd = new MySqlCommand(query, conn))
                        {
                            cmd.Transaction = trans;
                            //log.Debug(string.Format("cmd.CommandTimeout='{0}'", cmd.CommandTimeout));
                            cmd.CommandTimeout = 5000;
                            //log.Debug(string.Format("cmd.CommandTimeout='{0}'", cmd.CommandTimeout));

                            using (MySqlDataReader dr = cmd.ExecuteReader())
                            {
                                // Write the data to the console
                                //while (dr.Read())
                                //{
                                //    Console.WriteLine(dr["lotno"].ToString());
                                //}
                                ds = new System.Data.DataSet("Names");
                                while (!dr.IsClosed)
                                    ds.Tables.Add().Load(dr);
                                dr.Close();

                                DataTable dt = ds.Tables[0];

                                // Close the connection
                                conn.Close();

                                log.Debug(string.Format("  found {0} record.", dt.Rows.Count));
                                return dt;
                            }
                        }
                    }
                }
            }
            catch (MySqlException ex)
            {
                log.Error(ex.Message);
                return null;
            }
        }

        public static string ExecuteNonQuery(string query)
        {
            query = Regex.Replace(query, @"\s+", " ");
            log.Debug(query);

            try
            {
                string result = "";
                using (var conn = new MySqlConnection(connMySql))
                {
                    conn.Open();

                    using (MySqlTransaction myTrans = conn.BeginTransaction(IsolationLevel.ReadCommitted))
                    {
                        // Assign transaction object for a pending local transaction
                        using (MySqlCommand myCommand = new MySqlCommand())
                        {
                            myCommand.Connection = conn;
                            myCommand.Transaction = myTrans;

                            try
                            {
                                myCommand.CommandText = query;
                                myCommand.ExecuteNonQuery();

                                myTrans.Commit();
                                result = "success";
                                log.Info(result);
                            }
                            catch (Exception ex)
                            {
                                myTrans.Rollback();
                                result = ex.Message;
                                log.Error(ex.Message);
                            }
                        }
                    }
                }
                return result;
            }
            catch (MySqlException ex)
            {
                log.Error(ex.Message);
                return null;
            }
        }

    } // end class
}

4.สร้างคลาส mysql/qry.cs

using System.Reflection;

namespace ConsoleApp1.mysql
{
    public class qry
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        public static string QuerySelectData(string param1)
        {
            log.Info(string.Format("Parameter ({0})", param1));

            string query = string.Format(@"", param1);
            return query;
        }

        public static string QuerySelectData(string param1, string param2)
        {
            log.Info(string.Format("Parameter ({0}, {1})", param1, param2));

            string query = string.Format(@"", param1, param2);
            return query;
        }

    } // end class
}

5.แก้ไขไฟล์ App.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>

  <appSettings>
    <add key="connMySql" value="server=xxx.xxx.xxx.xxx;database=[dbname];uid=[userid];pwd=[userpass];" />
  </appSettings>

  <system.data>
    <DbProviderFactories>
      <remove invariant="MySql.Data.MySqlClient" />
      <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.12.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
    </DbProviderFactories>
  </system.data>
</configuration>

6.แก้ไขไฟล์ Program.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        static void Main(string[] args)
        {
            try
            {
                log.Info("*********************************");
                log.Info("************* BEGIN *************");
                log.Info(AppDomain.CurrentDomain.FriendlyName);


                // Check AppSettings in App.config
                if (!checkConfig())
                {
                    log.Error("Missing some config");
                    return;
                }


                string connMySql = ConfigurationManager.AppSettings.Get("connMySql");
                log.Info(string.Format("  '{0}'", connMySql.Split(';')[0]));

                mysql.sql.ExecuteReader(mysql.qry.QuerySelectData(""));


                log.Info("************** END **************");
                log.Info("");
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
                log.Error(ex.ToString());
            }
        } // end main

        private static bool checkConfig()
        {
            string connMySql = ConfigurationManager.AppSettings.Get("connMySql");
            if (string.IsNullOrEmpty(connMySql))
            {
                log.Error("'connMySql' not found in App.config");
                return false;
            }

            return true;
        }
    } // end class
}