主頁 > .NET開發 > 【ASP.NET Core學習】Entity Framework Core

【ASP.NET Core學習】Entity Framework Core

2020-09-21 07:05:14 .NET開發

<style>.cnblogs_code { width: auto; border-radius: 4px; box-shadow: 3px 2px 7px rgba(189, 183, 183, 1) } .ws-title { background-color: rgba(40, 120, 156, 1); font-size: 25px; font-family: "微軟雅黑"; padding: 8px 24px; border-radius: 4px; text-align: left; box-shadow: 1px 4px 5px 1px rgba(136, 136, 136, 1); color: rgba(255, 255, 255, 1); clear: both } .ws-content { margin-left: 20px; margin-top: 12px }</style>

 這里介紹在ASP.NET Core中使用EF Core,這里資料庫選的是Sql Server

  1. 如何使用Sql Server
  2. 添加模型 && 資料庫遷移
  3. 查詢資料
  4. 保存資料

如何使用Sql Server

 1. 安裝dotnet-ef(已經安裝忽略)
dotnet tool install --global dotnet-ef

2. 添加包Microsoft.EntityFrameworkCore.Design

dotnet add package Microsoft.EntityFrameworkCore.Design

3. 添加包Microsoft.EntityFrameworkCore.SqlServer

dotnet add package Microsoft.EntityFrameworkCore.SqlServer

4. 添加DbContext

public class EFCoreDbContext : DbContext
{
    public EFCoreDbContext(DbContextOptions<EFCoreDbContext> options)
        : base(options)
    {

    }
}
View Code

5.在ConfigureServices注入DbContext

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddDbContext<Data.EFCoreDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
View Code

 

經過上面5步,我們就可以在專案中使用資料庫,在需要的地方注入DbContext即可

 

添加模型

 我們就以學校 -> 學生這樣的模型(一對多)為例,欄位也盡量簡潔,這里不是展示設計,以展示操作EF Core為主,所以類定義未必是最合適的,  學校類
[Table("School")]
public class School
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Display(Name = "學校名稱")]
    [Required(ErrorMessage = "學校名稱不能為空")]
    [StringLength(100, ErrorMessage = "學校名稱最大長度為100")]
    public string Name { get; set; }

    [Display(Name = "學校地址")]
    [Required(ErrorMessage = "學校地址不能為空")]
    [StringLength(200, ErrorMessage = "學校地址最大長度為200")]
    public string Address { get; set; }

    public List<Student> Students { get; set; }

    [Display(Name = "創建時間")]
    [DataType(DataType.DateTime), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm:ss}")]
    public DateTime CreateTime { get; set; }

    [Display(Name = "最后更新時間")]
    [DataType(DataType.DateTime), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm:ss}")]
    public DateTime? LastUpdateTime { get; set; }
}
View Code

 學生類

public class Student
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Display(Name = "學生姓名")]
    [Required(ErrorMessage = "學生姓名不能為空")]
    [StringLength(50, ErrorMessage = "學生姓名最大長度為50")]
    public string Name { get; set; }

    [Display(Name = "年齡")]
    [Required(ErrorMessage = "年齡不能為空")]
    [Range(minimum: 10, maximum: 100, ErrorMessage = "學生年齡必須在(10 ~ 100)之間")]
    public int Age { get; set; }

    public School School { get; set; }

    [Display(Name = "創建時間")]
    [DataType(DataType.DateTime), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm:ss}")]
    public DateTime CreateTime { get; set; }

    [Display(Name = "最后更新時間")]
    [DataType(DataType.DateTime), DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm:ss}")]
    public DateTime? LastUpdateTime { get; set; }
}
View Code

配置默認值

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Models.School>()
                .Property(p => p.CreateTime)
                .HasDefaultValueSql("getdate()");

    modelBuilder.Entity<Models.Student>()
                .Property(p => p.CreateTime)
                .HasDefaultValueSql("getdate()");
}
View Code

模型定義好之后,我們需要把模型添加到DbContext

public DbSet<Models.School> Schools { get; set; }
public DbSet<Models.Student> Students { get; set; }
然后需要更新模型到資料庫,執行下面兩條命令 1. 新增一個遷移
dotnet ef migrations add DatabaseInit

 2. 更新到資料庫

dotnet ef migrations add DatabaseInit

查看資料庫,我們可以看到下面關系圖

 

在Student表里面多了一個SchoolId,這個我們是沒有定義,是EF Core生成的陰影屬性,當然我們也可以顯示定義這個欄位

物體類定義我們用到資料注釋和Fluent API約束物體類生成,下面列取經常用到的

注釋用途
 Key  主鍵
 Required  必須
 MaxLength   最大長度
NotMapped 不映射到資料庫
ConcurrencyCheck 并發檢查
Timestamp 時間戳欄位
 

查詢資料

一、聯接查詢
var query = from a in _context.School
            join b in _context.Student on a.Id equals b.School.Id
            select new
            {
                SchoolName = a.Name,
                StudentName = b.Name
            };
View Code

 對應生成的Sql

SELECT [s].[Name] AS [SchoolName], [t].[Name] AS [StudentName]
FROM [School] AS [s]
INNER JOIN (
    SELECT [s0].[Id], [s0].[Age], [s0].[CreateTime], [s0].[LastUpdateTime], [s0].[Name], [s0].[SchoolId], [s1].[Id] AS [Id0], [s1].[Address], [s1].[CreateTime] AS [CreateTime0], [s1].[LastUpdateTime] AS [LastUpdateTime0], [s1].[Name] AS [Name0]
    FROM [Student] AS [s0]
    LEFT JOIN [School] AS [s1] ON [s0].[SchoolId] = [s1].[Id]
) AS [t] ON [s].[Id] = [t].[Id0]

和我們預期有點不一致,預期是兩個表的全連接,為什么出現這個,原因是Student里面的導航屬性School,Linq遇到導航屬性是通過連表得到,為了驗證這個,我們不使用陰影屬性,顯示加上SchoolId試試

var query = from a in _context.School
                        join b in _context.Student on a.Id equals b.SchoolId
                        select new
                        {
                            SchoolName = a.Name,
                            StudentName = b.Name
                        };
View Code

對應生成的Sql

SELECT [s].[Name] AS [SchoolName], [s0].[Name] AS [StudentName]
            FROM [School] AS [s]
            INNER JOIN [Student] AS [s0] ON [s].[Id] = [s0].[SchoolId]

這次生成的Sql就很簡潔,跟預期一樣,所以如果使用聯接查詢,最好是避免使用陰影屬性

兩個Sql的執行計劃

 二、GroupBy查詢

var query = from a in _context.School
            join b in _context.Student on a.Id equals b.SchoolId
            group a by a.Name into t
            where t.Count() > 0
            orderby t.Key
            select new
            {
                t.Key,
                Count = t.Count(),
            };
View Code

對應生成的Sql

SELECT [s].[Name] AS [Key], COUNT(*) AS [Count]
FROM [School] AS [s]
INNER JOIN [Student] AS [s0] ON [s].[Id] = [s0].[SchoolId]
GROUP BY [s].[Name]
HAVING COUNT(*) > 0
ORDER BY [s].[Name]

EF Core 支持的聚合運算子如下所示

  • 平均值
  • 計數
  • LongCount
  • 最大值
  • 最小值
  • Sum

 三、左連接

var query = from a in _context.School
            join b in _context.Student on a.Id equals b.SchoolId into t1
            from t in t1.DefaultIfEmpty()
            select new
            {
                SchoolName = a.Name,
                StudentName = t.Name
            };
var list = query.AsNoTracking().ToList();
View Code

對應生成的Sql

SELECT [s].[Name] AS [SchoolName], [s0].[Name] AS [StudentName]
FROM [School] AS [s]
LEFT JOIN [Student] AS [s0] ON [s].[Id] = [s0].[SchoolId]

四、小結

全聯接時避免使用導航屬性連表

默認情況是跟蹤查詢,這表示可以更改這些物體實體,然后通過 SaveChanges() 持久化這些更改,

如果只需要讀取,不需要修改可以指定非跟蹤查詢AsNoTracking

非跟蹤查詢可以在每個查詢后面指定,還可以在背景關系實體級別更改默認跟蹤行為

context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

 

保存資料

一、關聯資料
_context.School.Add(new Models.School
{
    Name = "暨南大學",
    Address = "廣州市黃埔大道西601號",
    Students = new System.Collections.Generic.List<Models.Student>()
    {
        new Models.Student
        {
            Name= "黃偉",
            Age = 21,
        },
    },
});
    
_context.SaveChanges();
View Code

 同時在School,Student表保存資料,自動維護Student表的SchoolId欄位資料

 

二、級聯洗掉

var school = _context.School.Include(m => m.Students).FirstOrDefault(m => m.Name == "濟南大學");
    
    _context.School.Remove(school);
    
    _context.SaveChanges();
View Code 對應生成的Sql
--1. 讀取濟南大學和他所有學生
    SELECT [t].[Id], [t].[Address], [t].[CreateTime], [t].[LastUpdateTime], [t].[Name], [s0].[Id], [s0].[Age], [s0].[CreateTime], [s0].[LastUpdateTime], [s0].[Name], [s0].[SchoolId]
    FROM (
        SELECT TOP(1) [s].[Id], [s].[Address], [s].[CreateTime], [s].[LastUpdateTime], [s].[Name]
        FROM [School] AS [s]
        WHERE [s].[Name] = N'濟南大學'
    ) AS [t]
    LEFT JOIN [Student] AS [s0] ON [t].[Id] = [s0].[SchoolId]
    ORDER BY [t].[Id], [s0].[Id]
    
    --2. 回圈每個學生洗掉
    SET NOCOUNT ON;
    DELETE FROM [Student]
    WHERE [Id] = @p0;
    SELECT @@ROWCOUNT;
    SET NOCOUNT ON;
    DELETE FROM [Student]
    WHERE [Id] = @p0;
    SELECT @@ROWCOUNT;
    SET NOCOUNT ON;
    DELETE FROM [Student]
    WHERE [Id] = @p0;
    SELECT @@ROWCOUNT;
    
    --3. 洗掉學校
    SET NOCOUNT ON;
    DELETE FROM [School]
    WHERE [Id] = @p1;
    SELECT @@ROWCOUNT;
View Code

級聯洗掉要用Include把子項也包含到物體

 

三、使用事務

默認情況下,如果資料庫提供程式支持事務,則會在事務中應用對 SaveChanges() 的單一呼叫中的所有更改, 如果其中有任何更改失敗,則會回滾事務且所有更改都不會應用到資料庫, 這意味著,SaveChanges() 可保證完全成功,或在出現錯誤時不修改資料庫,

對于大多數應用程式,此默認行為已足夠, 如果應用程式要求被視為有必要,則應該僅手動控制事務中間呼叫多次SaveChanges()也不會直接保存到資料庫,最后transaction.Commit()

 

using (var transaction = _context.Database.BeginTransaction())
{
    var school = _context.School.Add(new Models.School
    {
        Name = "濟南大學",
        Address = "山東省濟南市南辛莊西路336號",
    });
    _context.SaveChanges();

    System.Threading.Thread.Sleep(2000);  //for testing
    _context.Student.Add(new Models.Student
    {
        Name = "張三",
        Age = 29,
        School = school.Entity
    });
    _context.SaveChanges();

    transaction.Commit();
}
View Code

 

下面是Sql Server Profiler

 

注意兩次RPC:Completed時間,每次呼叫SaveChanges提交到資料庫執行,外面包一層事務,所以事務里面要盡可能的控制操作最少,時間最少

 

四、并發沖突

EF Core實作的是樂觀并發,有關樂觀并發和悲觀并發這里就不展開,

EF處理并發分兩種情況,單個屬性并發檢查和時間戳(又叫行版本),單個屬性只保證單個欄位并發修改,時間戳是保證整條資料的并發修改

我們在Student的Age加上[ConcurrencyCheck],在School加上行版本

[ConcurrencyCheck]
public int Age { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }

1. 模擬Age并發沖突

var student = _context.Student.Single(m => m.Id == 1);
student.Age = 32;

#region 模擬另外一個用戶修改了Age

var task = Task.Run(() =>
{
    var options = HttpContext.RequestServices.GetService<DbContextOptions<Data.EFCoreDbContext>>();
    using (var context = new Data.EFCoreDbContext(options))
    {
        var student = context.Student.Single(m => m.Id == 1);
        student.Age = 23;
        context.SaveChanges();
    }
});
task.Wait();

#endregion

try
{
    _context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
    _logger.LogError(ex, "database update error");
}
View Code

2. 資料庫資料

 可以看到是Task里面的更新成功了

3. 例外資訊

Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded

例外資訊描述很明確,就是資料庫操作期望1行被影響,實際是0行,資料可能被修改或洗掉自從物體加載后

4. SQL

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Student] SET [Age] = @p0
WHERE [Id] = @p1 AND [Age] = @p2;
SELECT @@ROWCOUNT;

',N'@p1 int,@p0 int,@p2 int',@p1=1,@p0=23,@p2=25

exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Student] SET [Age] = @p0
WHERE [Id] = @p1 AND [Age] = @p2;
SELECT @@ROWCOUNT;

',N'@p1 int,@p0 int,@p2 int',@p1=1,@p0=32,@p2=25
View Code

加上并發檢查的欄位會在where條件后面加上原始值,Timestamp也是一樣道理,只是Timestamp是每次(插入/更新)資料庫會更新這個欄位,數字遞增的形式,

5. 解決并發沖突

要解決上面沖突,先要介紹EF Core里面三組數值

原始值:物體從資料庫加載時的值   (例子:Age = 25)

當前值:物體當前的值        (例子:Age = 32)

資料庫值:當前資料庫中的值     (例子:Age = 23)

public void SaveToDb()
{
    var student = _context.Student.Single(m => m.Id == 1);
    student.Age = 32;

    //模擬另外一個用戶修改了Age
    var task = Task.Run(() =>
    {
        var options = HttpContext.RequestServices.GetService<DbContextOptions<Data.EFCoreDbContext>>();
        using (var context = new Data.EFCoreDbContext(options))
        {
            var student = context.Student.Single(m => m.Id == 1);
            student.Age = 23;
            context.SaveChanges();
        }
    });
    task.Wait();
    //到這,另外一個執行緒已經將Age修改成23

    var trySave = 0;

    //若并發沖突例外,重試3次
    while (trySave++ < 3)
    {
        if (TrySaveData()) break;
    }

    bool TrySaveData()
    {
        try
        {
            _context.SaveChanges();
            return true;
        }
        catch (DbUpdateConcurrencyException ex)
        {
            _logger.LogError(ex, $"database update concurrency exception : retry: {trySave}");

            //3次嘗試保存失敗,拋出例外等上層處理,不應該吃掉例外,不然回傳成功,實際保存沒成功
            if (trySave >= 3) throw ex;

            //若沖突不是當前處理的物件,拋出例外等上層處理
            if (!ex.Entries.Any(m => m.Entity is Models.Student)) throw ex;

            var entry = ex.Entries.Select(m => m).Single(m => m.Entity is Models.Student);
            //獲取當前物體值
            var currentValues = entry.CurrentValues;
            //獲取資料庫值
            var databaseValues = entry.GetDatabaseValues();

            //這里獲取當前需要修改的欄位
            var property = currentValues.Properties.FirstOrDefault(m => m.Name == nameof(student.Age));
            var currentValue =https://www.cnblogs.com/WilsonPan/p/ currentValues[property];
            var databaseValue =https://www.cnblogs.com/WilsonPan/p/ databaseValues[property];

            //這里賦值多個選擇方案,1. 使用當前值 2. 使用資料庫值 3. 處理后的值(例如余額,資料庫余額 - 當前余額 & 大于0)
            currentValues[property] = currentValue;

            // 重繪原始值,這里原始值是做并發檢查
            entry.OriginalValues.SetValues(databaseValues);

            return false;
        }
    }
}
View Code

資料庫更新為我們預期的值

轉發請標明出處:https://www.cnblogs.com/WilsonPan/p/11792722.html

示例代碼:https://github.com/WilsonPan/AspNetCoreExamples/tree/master/EFCore

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/94909.html

標籤:.NET Core

上一篇:net core WebApi——April.Util更新之權限

下一篇:ASP.NET Core 3.0 使用AspectCore-Framework實作AOP

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more