在 Net Core 開發中如何解決 Cannot access a disposed object 這個問題

来源:https://www.cnblogs.com/PatrickLiu/archive/2023/05/31/17445451.html
-Advertisement-
Play Games

### 前言 當我們編寫 C# 代碼時,經常需要處理大量的數據集合。在傳統的方式中,我們往往需要先將整個數據集合載入到記憶體中,然後再進行操作。但是如果數據集合非常大,這種方式就會導致記憶體占用過高,甚至可能導致程式崩潰。 C# 中的`yield return`機制可以幫助我們解決這個問題。通過使用`y ...


一、簡介
    Net Core跨平臺項目開發多了,總會遇到各種各樣的問題,我就遇到了一個這樣的問題,不能訪問 Cannot access a disposed object 錯誤,經過自己多方努力,查閱資料,終於找到瞭解決辦法,引發這個問題的原因大多數是多次讀取請求Body流造成的,需要換一種獲取請求Body流方法,不能使用StreamRreader方式,使用Body.CopyTo(ms)方法。

            我使用的環境:Visual Studio 2022
    開發語言:C#
    開發框架:Asp.Net Core Mvc
    DotNet版本:Net 6.0

    遇到問題是好事,說明自己還有不足,那就解決它,時間長了,技術和知識也就積累了。其實解決方法不難,話不多,直接上解決方案。

二、解決方案的具體實現
   解決方法很簡單,不需要做過多解釋,直接找個配置和編碼就可以了,我貼完整源碼,是便於以後查閱,不喜勿噴。

    總共三步:紅色字體寫好了操作步驟(說明一下,紅色字體是要解決方法,其他不要關註,把整個代碼貼出來,是為了以後查閱

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using OpticalTrap.Framework.DataAccessors;
using OpticalTrap.Web.Facade.Extensions.Filters;
using OpticalTrap.Web.Facade.Utilities;
using OpticalTrap.Web.ServiceManager;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews(option =>
{
    option.Filters.Add(typeof(GlobalAuthorizationFilterAttribute));
    option.Filters.Add(typeof(GlobalOperationLogFilterAttribute));
}).AddXmlSerializerFormatters();

#region 第一步:配置可以同步請求讀取流數據

builder.Services.Configure<KestrelServerOptions>(k => k.AllowSynchronousIO = true)
    .Configure<IISServerOptions>(k => k.AllowSynchronousIO = true);

#endregion

#region 配置日誌

builder.Logging.AddLog4Net("ConfigFiles/log4net.config");

#endregion

#region 配置 Session

builder.Services.AddSession();

#endregion

#region 配置資料庫

builder.Services.AddTransientSqlSugar(builder.Configuration["ConnectionStrings:DefaultConnectionString"]);

#endregion

#region 配置區域

builder.Services.Configure<RazorViewEngineOptions>(option =>
{
    option.AreaViewLocationFormats.Clear();
    option.AreaViewLocationFormats.Add("/Areas/{2}/Views/{1}/{0}.cshtml");
    option.AreaViewLocationFormats.Add("/Areas/{2}/Views/Shared/{0}.cshtml");
    option.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
});

#endregion

#region 配置服務實例

builder.Services.AddBusinessServices();
builder.Services.AddUtilityServices();
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Services.AddSingleton<SessionCacheObjectProvider>();
builder.Services.AddTransient<AuthorizedDataGridGeneratorWrapper>();
builder.Services.AddSingleton<PageNumberGenerator>();

#endregion

#region 認證設置

builder.Services.AddAuthentication(option =>
{
    option.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    option.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    option.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    option.DefaultForbidScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    option.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
    options.LoginPath = "/Validation/Index";
    options.LogoutPath = "/Validation/Logout";
    options.AccessDeniedPath = "/Validation/Index";
    options.Cookie.HttpOnly = true;
    options.ClaimsIssuer = "Cookie";
});

#endregion

var app = builder.Build();

//第二步:啟用倒帶, 在發生異常時, 可以通過過濾器獲取post參數
app.Use((context, next) =>
{
    context.Request.EnableBuffering();
    return next(context);
});

if (app.Environment.IsProduction())
{
    app.UseStatusCodePagesWithReExecute("/ErrorHandler/HttpStatusCode", "?statusCode={0}");
    app.UseExceptionHandler("/ErrorHandler/ExceptionHandler");
}
else
{
    app.UseDeveloperExceptionPage();
}

app.UseStaticFiles();

app.UseSession();
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute("defaultAreaRoute", "{area:exists}/{controller=Home}/{action=Index}/{id?}");

app.MapControllerRoute("defaultRoute", "{controller=Home}/{action=Index}/{id?}");

app.Run();
 
        我寫了一個過濾器(實現日誌功能),實現的是IActionFilter 過濾器,在過濾器中,獲取Post請求Body的Context使用下麵方式獲取強調(強調,關註紅色字體,其他無關,這是我寫的日誌功能,貼全部代碼,便於以後查閱,不喜勿噴)
  1 using Microsoft.AspNetCore.Mvc.Filters;
  2 using Newtonsoft.Json;
  3 using OpticalTrap.Framework.Loggings;
  4 using OpticalTrap.Web.ConstProvider;
  5 using OpticalTrap.Web.Contracts;
  6 using OpticalTrap.Web.Facade.Controllers;
  7 using OpticalTrap.Web.Models;
  8 using System.Reflection;
  9 using System.Security.Claims;
 10 using System.Text;
 11 
 12 namespace OpticalTrap.Web.Facade.Extensions.Filters
 13 {
 14     /// <summary>
 15     /// 該類型定義了全局處理操作日誌的過濾器,該類型是密封類型。
 16     /// </summary>
 17     public sealed class GlobalOperationLogFilterAttribute : Attribute, IActionFilter, IAsyncActionFilter
 18     {
 19         #region 實例欄位
 20 
 21         private readonly ILogger<GlobalOperationLogFilterAttribute> _logger;
 22         private readonly IServiceProvider _serviceProvider;
 23 
 24         #endregion
 25 
 26         #region 構造函數
 27 
 28         /// <summary>
 29         /// 初始化該類型的新實例。
 30         /// </summary>
 31         /// <param name="logger">需要註入的日誌服務實例。</param>
 32         /// <param name="serviceProvider">需要註入的服務提供器。</param>
 33         public GlobalOperationLogFilterAttribute(ILogger<GlobalOperationLogFilterAttribute> logger, IServiceProvider serviceProvider)
 34         {
 35             _logger = logger;
 36             _serviceProvider = serviceProvider;
 37         }
 38 
 39         #endregion
 40 
 41         #region 操作日誌的同步方法
 42 
 43         /// <summary>
 44         /// 在標註方法執行之前執行該方法。
 45         /// </summary>
 46         /// <param name="context">方法執行前的上下文。</param>
 47         public async void OnActionExecuting(ActionExecutingContext context)
 48         {
 49             if (context.Controller.GetType() != typeof(ErrorHandlerController))
 50             {
 51                 if (context.ActionDescriptor.EndpointMetadata.Any(c => c.GetType() == typeof(RequiredLogAttribute)))
 52                 {
 53                     #region 核心處理
 54 
 55                     var controllerType = context.Controller.GetType();
 56                     var currentMethodName = context.ActionDescriptor.RouteValues["action"]!;
 57 
 58                     string? loginName = string.Empty;
 59                     var claimKeysProvider = _serviceProvider.GetService<ClaimKeysConstProvider>();
 60                     if (claimKeysProvider != null)
 61                     {
 62                         loginName = context.HttpContext.User.FindFirstValue(claimKeysProvider.ClaimStoreUserNameKey);
 63                     }
 64 
 65                     var currentDateTime = DateTime.Now;
 66                     var methodType = context.HttpContext.Request.Method;
 67                     string parameterResult = string.Empty;
 68                     if (string.Compare(methodType, "get", true) == 0)
 69                     {
 70                         if (!string.IsNullOrEmpty(context.HttpContext.Request.QueryString.Value) && !string.IsNullOrWhiteSpace(context.HttpContext.Request.QueryString.Value))
 71                         {
 72                             parameterResult = context.HttpContext.Request.QueryString.Value;
 73                         }
 74                     }
 75                     else
 76                     {
 77                         //第三步:在同步方法里的使用:啟用倒帶, 讀取request.body里的的參數, 還必須在在Program.cs里也啟用倒帶功能
 78                         context.HttpContext.Request.EnableBuffering();
 79                         context.HttpContext.Request.Body.Position = 0;
 80                         using (var memoryStream = new MemoryStream())
 81                         {
 82                             context.HttpContext.Request.Body.CopyTo(memoryStream);
 83                             var streamBytes = memoryStream.ToArray();
 84                             parameterResult = Encoding.UTF8.GetString(streamBytes); //把body賦值給bodyStr
 85                         }
 86                         //using (var reader = new StreamReader(context.HttpContext.Request.Body, Encoding.UTF8))
                        //{
                        //   var bodyRead = reader.ReadToEndAsync();
                        //   bodyStr = bodyRead.Result;  //把body賦值給bodyStr
                        //   needKey = JsonConvert.DeserializeAnonymousType
                //  (bodyRead.Result, new Dictionary<string, object>())[dependencySource].ToString();
                        //}
                if (controllerType != typeof(ValidationController))
 87                         {
 88                             parameterResult = ProcessFormParameters(parameterResult);
 89                         }
 90                         else
 91                         {
 92                             parameterResult = ProcessLoginUserNameParameters(parameterResult, controllerType, nameof(ValidationController), currentMethodName, out loginName);
 93                         }
 94                     }
 95 
 96                     parameterResult = !string.IsNullOrEmpty(parameterResult) ? parameterResult : "沒有傳遞任何參數";
 97                     loginName = !string.IsNullOrEmpty(loginName) ? loginName : "anonymous";
 98                     Guid userid = Guid.Empty;
 99                     if (string.IsNullOrEmpty(context.HttpContext.User.FindFirstValue(ClaimTypes.Sid)) || string.IsNullOrWhiteSpace(context.HttpContext.User.FindFirstValue(ClaimTypes.Sid)))
100                     {
101                         userid = Guid.Parse("a05897f9-0c86-4f5a-a581-e5da936d0e4c");
102                     }
103                     else
104                     {
105                         userid = Guid.Parse(context.HttpContext.User.FindFirstValue(ClaimTypes.Sid));
106                     }
107 
108                     OperationLog log = new OperationLog()
109                     {
110                         Id = Guid.NewGuid(),
111                         Name = $"{loginName}在{currentDateTime.ToString("yyyy-MM-dd HH:mm:ss")}執行了{currentMethodName}操作。",
112                         LoginName = loginName,
113                         Parameters = parameterResult,
114                         ActionName = $"{controllerType.FullName}.{currentMethodName}",
115                         ActionType = methodType,
116                         Message = $"【{loginName}】用戶在【{currentDateTime.ToString("yyyy-MM-dd HH:mm:ss")}】執行了控制器【{controllerType.FullName}】的【{currentMethodName}】方法,執行方法的類型:{methodType},執行方法所需的參數:【{parameterResult}】,操作順利完成。",
117                         Remarks = "全局日誌記錄器記錄的日誌。",
118                         CreateUserId = userid,
119                         CreateDate = currentDateTime
120                     };
121 
122                     try
123                     {
124                         MethodInfo? methodInfo;
125                         if (controllerType.IsDefined(typeof(RequiredLogAttribute), false))
126                         {
127                             methodInfo = controllerType.GetMethod(currentMethodName);
128                             if (methodInfo != null)
129                             {
130                                 _logger.LogInformation(JsonConvert.SerializeObject(log));
131                             }
132                         }
133                         else
134                         {
135                             methodInfo = controllerType.GetMethod(currentMethodName);
136                             if (methodInfo != null)
137                             {
138                                 if (methodInfo.IsDefined(typeof(RequiredLogAttribute), false))
139                                 {
140                                     _logger.LogInformation(JsonConvert.SerializeObject(log));
141                                 }
142                             }
143                         }
144                     }
145                     catch (Exception ex)
146                     {
147                         log.Name = $"異常操作日誌:{loginName}在{currentDateTime.ToString("yyyy-MM-dd HH:mm:ss")}執行了{currentMethodName}操作。";
148 
149                         log.Message = $"【{loginName}】用戶在【{currentDateTime.ToString("yyyy-MM-dd HH:mm:ss")}】執行了控制器【{controllerType.FullName}】的【{currentMethodName}】方法,執行方法的類型:{methodType},執行方法所需的參數:【{parameterResult}】,操作沒有完成,系統發生了異常。<br/>異常詳情:{ex.Message},<br/>異常堆棧:{ex.StackTrace}。";
150 
151                         _logger.LogInformation(JsonConvert.SerializeObject(log));
152                     }
153 
154                     #endregion
155                 }
156             }
157         }
158 
159         /// <summary>
160         /// 在標註方法執行之後執行該方法。
161         /// </summary>
162         /// <param name="context">方法執行後的上下文。</param>
163         public void OnActionExecuted(ActionExecutedContext context) { }
164 
165         #endregion
166 
167         #region 操作日誌的非同步方法
168 
169         /// <summary>
170         /// 全局日誌記錄器非同步實現的操作日誌的記錄。
171         /// </summary>
172         /// <param name="context">方法執行前的上下文。</param>
173         /// <param name="next">方法執行的下一個環節代理。</param>
174         /// <returns></returns>
175         public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
176         {
177             if (context.Controller.GetType() != typeof(ErrorHandlerController))
178             {
179                 if (context.ActionDescriptor.EndpointMetadata.Any(c => c.GetType() == typeof(RequiredLogAttribute)))
180                 {
181                     #region 核心處理
182 
183                     var controllerType = context.Controller.GetType();
184                     var currentMethodName = context.ActionDescriptor.RouteValues["action"]!;
185 
186                     string? loginName = string.Empty;
187                     var claimKeysProvider = _serviceProvider.GetService<ClaimKeysConstProvider>();
188                     if (claimKeysProvider != null)
189                     {
190                         loginName = context.HttpContext.User.FindFirstValue(claimKeysProvider.ClaimStoreUserNameKey);
191                     }
192 
193                     var currentDateTime = DateTime.Now;
194                     var methodType = context.HttpContext.Request.Method;
195                     string parameterResult = string.Empty;
196                     if (string.Compare(methodType, "get", true) == 0)
197                     {
198                         if (!string.IsNullOrEmpty(context.HttpContext.Request.QueryString.Value) && !string.IsNullOrWhiteSpace(context.HttpContext.Request.QueryString.Value))
199                         {
200                             parameterResult = context.HttpContext.Request.QueryString.Value;
201                         }
202                     }
203                     else
204                     {
205                         //第三步:在非同步步方法里的使用:啟用倒帶, 讀取request.body里的的參數, 還必須在在Program.cs里也啟用倒帶功能
206                         context.HttpContext.Request.EnableBuffering();
207                         context.HttpContext.Request.Body.Position = 0;
208                         using (var memoryStream = new MemoryStream())
209                         {
210                             context.HttpContext.Request.Body.CopyTo(memoryStream);
211                             var streamBytes = memoryStream.ToArray();
212                             parameterResult = Encoding.UTF8.GetString(streamBytes); //把body賦值給bodyStr
213                         }
                //using (var reader = new StreamReader(context.HttpContext.Request.Body, Encoding.UTF8))
                        //{
                        //   var bodyRead = reader.ReadToEndAsync();
                        //   bodyStr = bodyRead.Result;  //把body賦值給bodyStr
                        //   needKey = JsonConvert.DeserializeAnonymousType
                //  (bodyRead.Result, new Dictionary<string, object>())[dependencySource].ToString();
                        //}
214 if (controllerType != typeof(ValidationController)) 215 { 216 parameterResult = ProcessFormParameters(parameterResult); 217 } 218 else 219 { 220 parameterResult = ProcessLoginUserNameParameters(parameterResult, controllerType, nameof(ValidationController), currentMethodName, out loginName); 221 } 222 } 223 224 parameterResult = !string.IsNullOrEmpty(parameterResult) ? parameterResult : "沒有傳遞任何參數"; 225 loginName = !string.IsNullOrEmpty(loginName) ? loginName : "anonymous"; 226 Guid userid = Guid.Empty; 227 if (string.IsNullOrEmpty(context.HttpContext.User.FindFirstValue(ClaimTypes.Sid)) || string.IsNullOrWhiteSpace(context.HttpContext.User.FindFirstValue(ClaimTypes.Sid))) 228 { 229 userid = Guid.Parse("a05897f9-0c86-4f5a-a581-e5da936d0e4c"); 230 } 231 else 232 { 233 userid = Guid.Parse(context.HttpContext.User.FindFirstValue(ClaimTypes.Sid)); 234 } 235 236 OperationLog log = new OperationLog() 237 { 238 Id = Guid.NewGuid(), 239 Name = $"{loginName}在{currentDateTime.ToString("yyyy-MM-dd HH:mm:ss")}執行了{currentMethodName}操作。", 240 LoginName = loginName, 241 Parameters = parameterResult, 242 ActionName = $"{controllerType.FullName}.{currentMethodName}", 243 ActionType = methodType, 244 Message = $"【{loginName}】用戶在【{currentDateTime.ToString("yyyy-MM-dd HH:mm:ss")}】執行了控制器【{controllerType.FullName}】的【{currentMethodName}】方法,執行方法的類型:{methodType},執行方法所需的參數:【{parameterResult}】,操作順利完成。", 245 Remarks = "全局日誌記錄器記錄的日誌。", 246 CreateUserId = userid, 247 CreateDate = currentDateTime 248 }; 249 250 try 251 { 252 MethodInfo? methodInfo; 253 if (controllerType.IsDefined(typeof(RequiredLogAttribute), false)) 254 { 255 methodInfo = controllerType.GetMethod(currentMethodName); 256 if (methodInfo != null) 257 { 258 _logger.LogInformation(JsonConvert.SerializeObject(log)); 259 } 260 } 261 else 262 { 263 methodInfo = controllerType.GetMethod(currentMethodName); 264 if (methodInfo != null) 265 { 266 if (methodInfo.IsDefined(typeof(RequiredLogAttribute), false)) 267 { 268 _logger.LogInformation(JsonConvert.SerializeObject(log)); 269 } 270 } 271 } 272 } 273 catch (Exception ex) 274 { 275 log.Name = $"異常操作日誌:{loginName}在{currentDateTime.ToStr
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ## 併發與並行😣 ### 併發與並行的概念和區別 並行:同一個時間段內多個任務同時在不同的CPU核心上執行。強調同一時刻多個任務之間的”**同時執行**“。 併發:同一個時間段內多個任務都在進展。強調多個任務間的”**交替執行**“。 ![](https://img2023.cnblogs.co ...
  • 摘要:在讀多寫少的環境中,有沒有一種比ReadWriteLock更快的鎖呢?有,那就是JDK1.8中新增的StampedLock! 本文分享自華為雲社區《【高併發】高併發場景下一種比讀寫鎖更快的鎖》,作者: 冰 河。 什麼是StampedLock? ReadWriteLock鎖允許多個線程同時讀取共 ...
  • ###BIO:同步阻塞 主線程發起io請求後,需要等待當前io操作完成,才能繼續執行。 ###NIO:同步非阻塞 引入selector、channel、等概念,當主線程發起io請求後,輪詢的查看系統是否準備好執行io操作,沒有準備好則主線程不會阻塞會繼續執行,準備好主線程會阻塞等待io操作完成。 # ...
  • 在前面的幾篇文章中,詳細地給大家介紹了Java里的集合。但在介紹集合時,我們涉及到了泛型的概念卻並沒有詳細學習,所以今天我們要花點時間給大家專門講解什麼是泛型、泛型的作用、用法、特點等內容 ...
  • # Rust Web 全棧開發之 Web Service 中的錯誤處理 ## Web Service 中的統一錯誤處理 ### Actix Web Service 自定義錯誤類型 -> 自定義錯誤轉為 HTTP Response - 資料庫 - 資料庫錯誤 - 串列化 - serde 錯誤 - I/ ...
  • 1. 透過現象看本質 反射被譽為是 c#中的黑科技 ,在很多領域中都有反射的身影,例如,我們經常使用的ORM框架,ABP框架 等。 反射指程式可以訪問、檢測和修改它本身狀態或行為的一種能力。. 程式集包含模塊,而模塊包含類型,類型又包含成員。. 反射則提供了封裝程式集、模塊和類型的對象。. 您可以使 ...
  • 1. 為什麼需要單元測試 在我們之前,測試某些功能是否能夠正常運行時,我們都將代碼寫到Main方法中,當我們測試第二個功能時,我們只能選擇將之前的代碼清掉,重新編寫。此時,如果你還想重新測試你之前的功能時,這時你就顯得有些難為情了,因為代碼都被你清掉了。當然你完全可以把代碼寫到一個記事本中進行記錄, ...
  • 1. ADO.NET的前世今生 ADO.NET的名稱起源於ADO(ActiveX Data Objects),是一個COM組件庫,用於在以往的Microsoft技術中訪問數據。之所以使用ADO.NET名稱,是因為Microsoft希望表明,這是在NET編程環境中優先使用的數據訪問介面。 ADO.NE ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...