Opencc Memory Leak

近期專案上有個需求,需要使用opencc來將接收到的資料將簡體轉繁體,參考了will保哥與黑暗執行緒的範例,其中保哥的文章指出有做防止記憶體洩漏的調整,但上線後發現一樣有記憶體洩漏的問題,最後找到的解決方案是,應該要使用opencc的函式做記憶體釋放,而非使用C#的函式。 調整前 using System.Runtime.InteropServices; using System.Text; public static class OpenCCHelper { [DllImport(@"C:\Tools\opencc\bin\opencc.dll", EntryPoint = "opencc_open")] private static extern IntPtr opencc_open(string configFileName); [DllImport(@"C:\Tools\opencc\bin\opencc.dll", EntryPoint = "opencc_convert_utf8")] private static extern IntPtr opencc_convert_utf8(IntPtr opencc, IntPtr input, long length); public static string ConvertFromSimplifiedToTraditional(this string text, string config = "s2t") { return OpenCC(text, config: config); } public static string ConvertFromSimplifiedToTraditionalTaiwan(this string text, string config = "s2twp") { return OpenCC(text, config: config); } public static string ConvertFromTraditionalTaiwanToSimplified(this string text, string config = "tw2sp") { return OpenCC(text, config: config); } public static string ConvertFromTraditionalToSimplified(this string text, string config = "t2s") { return OpenCC(text, config: config); } public static string OpenCC(this string text, string config) { var configFile = $"C:\\Tools\\OpenCC\\share\\opencc\\{config}....

May 19, 2024

Dapper PostgreSQL Error

問題 當使用dapper呼叫postgresql時後,需要在in裡面查詢一批陣列會遇到下方的錯誤訊息 var Ids = [1,2,3,4]; DynamicParameters parameters = new(); parameters.Add("Ids", Ids); var strSQL = ""; strSQL +="select * from Users where id in @Ids;" await dapper.QueryAsync(strSQL,parameters); 42601: syntax error at or near “$1”\r\n\r\nPOSITION: 81 解法 改語法為any就可以解決這個問題。 var Ids = [1,2,3,4]; DynamicParameters parameters = new(); parameters.Add("Ids", Ids); var strSQL = ""; strSQL +="select * from Users where id = any(@Ids);" await dapper.QueryAsync(strSQL,parameters);

November 24, 2023

dotnet6 Hangfire範例

目的 在windows系統上想執行排程有兩個選擇 使用windows工作排程器執行exe檔 透過Hangfire進行排程管理 此次教學說明如何使用Hangfire執行排程 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 NuGet加入套件 Hangfire Hangfire.InMemory 編輯Program.cs檔 using Hangfire; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //註冊hangfire並且使用記憶體保存排程, //預設所下載的HangFire套件可以使用sqlserver,可透過config.UseSqlServerStorage();,但需要設定 builder.Services.AddHangfire(config => { config.UseInMemoryStorage(); }); //註冊hangfire要使用的伺服器,伺服器就是上面所寫的使用記憶體當伺服器 builder.Services.AddHangfireServer(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); //使用hangfire內建的儀表板 app.UseHangfireDashboard(); app....

October 11, 2022

dotnet6 HttpClient單元測試範例

目的 面試的時候被問到要如何做包含外部api的單元測試問題,稍微查一下其實很簡單,怎麼當下答不出來呢? 主要有兩種方式,一種為.net core 2.1以後有提供IHttpClientFactory的介面可以使用。 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 建立資料夾 編輯Program.cs檔案 註冊AddHttpClient。 builder.Services.AddHttpClient(); 新增一個類別檔 加入前 加入後 建構子注入 將註冊的httpclient透過建構子注入 readonly IHttpClientFactory _httpClientFactory; public CallAPIServices(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } 加入前 加入後 新增方法 新增一個會去發外部請求的方法,模擬當有包含第三方api時如何測試 public async Task<string> Get() { var client = _httpClientFactory.CreateClient(); var response = await client.GetAsync("https://example.com"); if (response.IsSuccessStatusCode) { var responseString = await response.Content.ReadAsStringAsync(); return responseString; } return ""; } 新增測試專案 對方案點選右鍵>加入>新增專案 設定新的專案 替測試專案命名,建議命名規則以.Tests做結尾 其他資訊 專案架構需要與要測試的專案相同 加入參考 將要測試的專案加入測試專案...

October 10, 2022

dotnet6 Moq範例

目的 進行單元測試時,可以隔絕依賴的項目。 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 建立新的類別庫 進行命名時通常會與要測試的專案同名並加上結尾.Tests,以此範例就會變成MoqExample.Tests NuGet加入套件 針對xUnitExample.Tests加入相關套件 xunit xunit.runner.visualstudio Microsoft.NET.Test.Sdk coverlet.collector Moq 針對MoqExample.Tests類別庫加入參考 引用要測試的專案,才能將測試與實際專案切分開來 新增WeatherForecastControllerTests.cs類別檔 刪除預設的類別檔(Class1.cs),並在MoqExample.Tests專案新增對應資料夾,與類別檔並加結尾Tests。 編輯WeatherForecastControllerTests.cs類別檔 測試都會分三個階段 Arrange:準備階段,包含初始化相關資料 Act:執行測試方法後所取得的結果 Assert:驗證Act取得的結果是否符合預期結果 這次要測試的是controller,有注入Ilogger,如何將Ilogger隔開的關鍵就是使用Moq這個套件 using Microsoft.Extensions.Logging; using Moq; using MoqExample.Controllers; using Xunit; namespace MoqExample.Tests.Controllers { public class WeatherForecastControllerTests { [Fact] public void Get() { //Arrange //透過mock將外界的介面包起來 var MockLogger = new Mock<ILogger<WeatherForecastController>>(); //當成物件傳入controller,代替實際的介面 var Controllers = new WeatherForecastController(MockLogger.Object); //Act //執行要測試的函式 var Results = Controllers.Get(); //Assert //確認結果不為null Assert....

October 9, 2022

dotnet6 NLog進階範例

目的 在寫nlog.config檔案時覺得怎麼有點複雜,我只是需要簡單的設定檔就好了,最後決定透過appsetting來做設定 將log文件採用非同步寫入,可大幅提升效能 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 4.NuGet加入套件 NLog NLog.Web.AspNetCore 編輯Program.cs檔 using NLog; using NLog.Web; //初始化NLog var logger = LogManager.Setup() //載入Configuration並且讀取appsetting來使用 .LoadConfigurationFromAppSettings() .GetCurrentClassLogger(); try { logger.Debug("init main"); var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Logging.ClearProviders(); builder.Host.UseNLog(); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //以下省略 編輯appsetting.json 設定NLog,包含 throwConfigExceptions:設定檔錯誤時會跳exception 使用非同步方式寫入檔案 targets:設定輸出的格式,例如txt檔案或是Console顯示 rules:什麼情況要做什麼動作,例如log名稱為Microsoft.AspNetCore最小等級是warn時寫到Console ILogger NLog Level 0 Trace Trace Level 1 Debug Debug Level 2 Information Info Level 3 Warning Warn Level 4 Error Error Level 5 Critical Fatal Level 6 None NLog沒有 { "NLog": { "throwConfigExceptions": true, "targets": { "async": true, "logfile": { "type": "File", "fileName": "c:/temp/nlog-${shortdate}....

October 8, 2022

dotnet6 xUnit範例

目的 單元測試 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 建立新的類別庫 進行命名時通常會與要測試的專案同名並加上結尾.Tests,以此範例就會變成xUnitExample.Tests NuGet加入套件 針對xUnitExample.Tests加入相關套件 xunit xunit.runner.visualstudio Microsoft.NET.Test.Sdk coverlet.collector 新增Calculator.cs類別檔 在xUnitExample專案新增Calculator.cs類別檔 新增一個簡單的加法函式 public static class Calculator { public static double Add(int a, int b) { return a + b; } } 針對xUnitExample.Tests類別庫加入參考 引用要測試的專案,才能將測試與實際專案切分開來 新增CalculatorTests.cs類別檔 刪除預設的類別檔(Class1.cs),建立對應的資料夾以及類別檔案,並在結尾加上Tests 編輯CalculatorTests.cs類別檔 測試都會分三個階段 Arrange:準備階段,包含初始化相關資料 Act:執行測試方法後所取得的結果 Assert:驗證Act取得的結果是否符合預期結果 public class CalculatorTests { //告訴編譯器要執行的測試方法 [Fact] public void Add_() { //Arrange double Expected = 20; //Act var Actual = Calculator.Add(5, 15); //Assert Assert....

October 8, 2022

dotnet6 NLog範例

目的 在webapi專案下使用NLog套件 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 NuGet加入套件 NLog NLog.Web.AspNetCore 新增nlog.config檔案 在根目錄新增nlog.config檔案 nlog.config寫入程式 在nlog.config寫入官方範例 <?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="Info" internalLogFile="c:\temp\internal-nlog-AspNetCore.txt"> <!-- enable asp.net core layout renderers --> <extensions> <add assembly="NLog.Web.AspNetCore"/> </extensions> <!-- the targets to write to --> <targets> <!-- File Target for all log messages with basic details --> <target xsi:type="File" name="allfile" fileName="c:\temp\nlog-AspNetCore-all-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" /> <!-- File Target for own log messages with extra web details using some ASP....

October 8, 2022

dotnet6 Serilog進階範例

目的 讀取appsetting設定檔 二階段初始化 為了簡單化故將Log存入SQLite 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 NuGet加入套件 Serilog.AspNetCore Serilog.Sinks.SQLite 編輯Program.cs檔 using Serilog; //第一階段初始化 // var builder = WebApplication.CreateBuilder(args);未使用二階段參數化,builder會跑到try外面 Log.Logger = new LoggerConfiguration() //.ReadFrom.Configuration(builder.Configuration) .CreateBootstrapLogger(); try { var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //第二階段初始化可以取得appsetting的內容,如不使用第二階段初始化, //會需要將 var builder宣告式會移出try(如上方註解處),就會有風險未捕獲builder的錯誤 builder.Host.UseSerilog( (hostingContext, services, loggerConfiguration) => { //使用appsetting loggerConfiguration.ReadFrom.Configuration(builder.Configuration); }); var app = builder....

October 7, 2022

dotnet6 Serilog範例

目的 在webapi專案下使用serilog套件 建立新專案 選擇ASP.NET Core Web API專案範本,並執行下一步 設定新的專案 命名你的專案名稱,並選擇專案要存放的位置。 其他資訊 直接進行下一步 NuGet加入套件 Serilog.AspNetCore 編輯Program.cs檔 在最外層包一個try catch目的是為了捕捉啟動階段的錯誤 using Serilog; using Serilog.Events; Log.Logger = new LoggerConfiguration() //Serilog要寫入的最低等級為Information .MinimumLevel.Information() //Microsoft.AspNetCore開頭的類別等極為warning .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning) //寫log到Logs資料夾的log.txt檔案中,並且以天為單位做檔案分割 .WriteTo.File("./Logs/log.txt", rollingInterval: RollingInterval.Day) .CreateLogger(); try { Log.Information("Starting web host"); var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); //controller可以使用ILogger介面來寫入log紀錄 builder.Host.UseSerilog(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run(); return 0; } catch (Exception ex) { Log....

October 7, 2022