ShowProgramCode

2023年6月14日 星期三

C# Net6 WebAPI或MVC架構下 Nlog+EFCore+MSSQL設定 自動記錄SQL命令

首先建立一個Net6 WebAPI或MVC專案

下面使用WebAPI專案作為示範,不過MVC專案設定大致相同,除了不需要手動增加Model資料夾...

一、設定Nlog

1.使用NuGet管理員,下載NLog.Web.AspNetCore,此次使用版本5.3.0。

2.在專案中手動增加nlog.config檔案。

記得必須選擇"永遠複製"到輸出目標。
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. autoReload="true"
  5. internalLogLevel="Error">
  6. <!-- 啟用 ASP.NET Core layout renderers -->
  7. <extensions>
  8. <add assembly="NLog.Web.AspNetCore"/>
  9. </extensions>
  10. <!-- 設定log根目錄 -->
  11. <variable name="logDirectory" value="C:\TWBank_Log\NlogTest" />
  12. <!-- log 儲存目標 -->
  13. <targets>
  14. <target xsi:type="File" name="allfile" fileName="${logDirectory}\nlog-all-${shortdate}.log"
  15. layout="${date:format=HH\:mm\:ss\.ffff} [thread:${threadid}] ${level:uppercase=true} ${message} ${exception:Format=ToString}" createDirs="true" encoding="UTF-8" />
  16. </targets>
  17. <!-- 設定 logger 名稱與 log 儲存目標的對應 -->
  18. <rules>
  19. <!--將Microsoft與System.Net.Http的錯誤拿掉不紀錄-->
  20. <logger name="Microsoft.*" maxlevel="Info" final="true" />
  21. <logger name="System.Net.Http.*" maxlevel="Info" final="true" />
  22. <logger name="*" minlevel="Trace" writeTo="allfile" />
  23. </rules>
  24. </nlog>

3.修改Program.cs

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. var builder = WebApplication.CreateBuilder(args);
  6.  
  7. //將NLog註冊到此專案內
  8. builder.Logging.ClearProviders();
  9. builder.Host.UseNLog();
  10.  
  11. ...
  12. var app = builder.Build();
  13. ...
  14. app.Run();
  15. }
  16. }

4.調整appsettings.json

Logging.LogLevel.Default可以控制預設紀錄的Log層級,目前Trace是最低層級,也就是什麼都會記錄。
  1. {
  2. "Logging": {
  3. "LogLevel": {
  4. "Default": "Trace",
  5. "Microsoft.AspNetCore": "Warning"
  6. }
  7. },
  8. "AllowedHosts": "*"
  9. }

5.修改範本Controller程式碼

Nlog支援將List、物件等,轉換成json string顯示,參考下方程式碼。
  1. [HttpGet(Name = "GetWeatherForecast")]
  2. public IEnumerable<WeatherForecast> Get()
  3. {
  4. IEnumerable<WeatherForecast> temp = Enumerable.Range(1, 5).Select(index => new WeatherForecast
  5. {
  6. Date = DateTime.Now.AddDays(index),
  7. TemperatureC = Random.Shared.Next(-20, 55),
  8. Summary = Summaries[Random.Shared.Next(Summaries.Length)]
  9. })
  10. .ToList();
  11. _logger.LogDebug("WeatherForecast List = {@temp}", temp);
  12. return temp;
  13. }

6.確認Log內容

二、設定EFCore,此處設定MSSQL,如果要設定不同資料庫,下載與設定方式會略有不同。

1.使用NuGet管理員,下載EFCore。

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.Sqlite

2.手動增加Model資料夾,並在內部加入MyDbContext繼承DbContext

  1. public class MyDbContext: DbContext
  2. {
  3. public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
  4. {
  5. }
  6. public DbSet<TestUser> User { get; set; }
  7. }
  8.  
  9. [Table("TestUser")]
  10. public class TestUser
  11. {
  12. [Key]
  13. public int Id { get; set; }
  14. [Required]
  15. [StringLength(20)]
  16. public string Name { get; set; } = string.Empty;
  17. [Required]
  18. [StringLength(15)]
  19. public string Phone { get; set; } = string.Empty;
  20. }

3.修改appsettings.json

設定遠端資料庫連線。
開發期間資料庫證書無法設定時,可以添加這個設定,TrustServerCertificate=true,將無條件信任IIS預設證書。
此外,還需要加上Logging設定中Microsoft.EntityFrameworkCore.Database.Command設定,並且在nlog.config必須一起設定。
  1. {
  2. "ConnectionStrings": {
  3. "DefaultConnection": "server=資料庫IP;user id=資料庫帳號;password=資料庫密碼;database=資料庫名稱;TrustServerCertificate=true"
  4. },
  5. "Logging": {
  6. "LogLevel": {
  7. "Default": "Trace",
  8. "Microsoft.AspNetCore": "Warning",
  9. "Microsoft.EntityFrameworkCore.Database.Command": "Information"
  10. }
  11. },
  12. "AllowedHosts": "*"
  13. }

4.調整nlog.config檔案。

針對Microsoft.EntityFrameworkCore.Database.Command設定
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. autoReload="true"
  5. internalLogLevel="Error">
  6. ...
  7. <!-- 設定 logger 名稱與 log 儲存目標的對應 -->
  8. <rules>
  9. <!--寫入SQL-->
  10. <logger name="Microsoft.EntityFrameworkCore.Database.Command" minlevel="Info" writeTo="allfile" />
  11. ...
  12. </rules>
  13. </nlog>

5.修改Program.cs

增加EFCore設定。
  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. var builder = WebApplication.CreateBuilder(args);
  6. //註冊EFCoreContext
  7. //先注入EFCore再注入Nlog才會記錄SQL命令
  8. string connectString = builder.Configuration.GetConnectionString("DefaultConnection");
  9. builder.Services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectString));
  10.  
  11. //將NLog註冊到此專案內
  12. builder.Logging.ClearProviders();
  13. builder.Host.UseNLog();
  14.  
  15. ...
  16. var app = builder.Build();
  17. ...
  18. app.Run();
  19. }
  20. }
  21.  

6.修改範本Controller程式碼

  1. private readonly ILogger<WeatherForecastController> _logger;
  2. private readonly MyDbContext _dbContext;
  3.  
  4. public WeatherForecastController(MyDbContext dbContext,ILogger<WeatherForecastController> logger)
  5. {
  6. _dbContext = dbContext;
  7. _logger = logger;
  8. }
  9.  
  10. public IEnumerable<WeatherForecast> Get()
  11. {
  12. IEnumerable<WeatherForecast> temp = Enumerable.Range(1, 5).Select(index => new WeatherForecast
  13. {
  14. Date = DateTime.Now.AddDays(index),
  15. TemperatureC = Random.Shared.Next(-20, 55),
  16. Summary = Summaries[Random.Shared.Next(Summaries.Length)]
  17. })
  18. .ToList();
  19.  
  20. IEnumerable<TestUser> temp2 = _dbContext.User.ToList();
  21.  
  22. _logger.LogDebug("WeatherForecast List = {@temp}", temp);
  23. _logger.LogDebug("TestUser List = {@temp}", temp2);
  24. return temp;
  25. }

7.確認Log內容與資料庫比對

Log內容:
資料庫內容:

由此可以確認資料庫中的內容與Log TestUser是一致的。
此外,如果Log內容不正確,可以將專案清除再重建,可能是什麼被cache造成的。