問題來自.Net開發群友 問題 我想做一個自動生成單據號的功能,但是在EFCORE里沒有行級鎖,請有什麼等價方案嗎? ChatGPT回答 在 EF Core 中確實沒有提供行級鎖(row-level locking)的功能,因為這需要對資料庫進行顯式的鎖定操作,而 EF Core 的設計理念是儘可能 ...
問題來自.Net開發群友
問題
我想做一個自動生成單據號的功能,但是在EFCORE里沒有行級鎖,請有什麼等價方案嗎?
ChatGPT回答
在 EF Core 中確實沒有提供行級鎖(row-level locking)的功能,因為這需要對資料庫進行顯式的鎖定操作,而 EF Core 的設計理念是儘可能不與資料庫直接交互,而是通過抽象層面的數據操作來實現,因此不鼓勵使用顯式的鎖定操作。
不過,在 EF Core 中提供了樂觀併發控制(Optimistic Concurrency Control)的功能,可以用於處理類似於行級鎖的需求。樂觀併發控制基於版本號(Version)機制實現,每個實體對象都有一個版本號屬性,當兩個用戶同時更新同一個實體對象時,EF Core 會比較它們的版本號,如果版本號不一致,則表示有衝突發生,需要執行相應的衝突解決邏輯。
因此,如果你想實現自動生成單據號的功能,並保證其唯一性,可以考慮使用樂觀併發控制的方案。具體的實現思路如下:
-
在你的實體對象中增加一個版本號屬性,類型為整數。
-
在生成單據號前,使用 EF Core 查詢最後一條記錄的單據號和版本號,得到最新的單據號和版本號。
-
在生成單據號時,將版本號加 1,並將單據號和版本號寫入到新的記錄中。如果寫入資料庫時發生衝突,則表示有其他用戶同時在生成單據號,此時可以重新獲取最新的單據號和版本號,並再次嘗試生成。
以下是一個簡單的示例代碼,演示瞭如何使用樂觀併發控制來生成唯一的單據號
public class Order
{
public int Id { get; set; }
public string OrderNo { get; set; }
public int Version { get; set; }
}
public class OrderContext : DbContext
{
public DbSet<Order> Orders { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.Property(o => o.Version)
.IsConcurrencyToken();
}
}
public class OrderService
{
private readonly OrderContext _context;
public OrderService(OrderContext context)
{
_context = context;
}
public string GenerateOrderNo()
{
string lastOrderNo = _context.Orders
.OrderByDescending(o => o.Id)
.Select(o => o.OrderNo)
.FirstOrDefault();
int lastVersion = _context.Orders
.OrderByDescending(o => o.Id)
.Select(o => o.Version)
.FirstOrDefault();
string newOrderNo = GenerateNewOrderNo(lastOrderNo);
var order = new Order
{
OrderNo = newOrderNo,
Version = lastVersion + 1
};
_context.Orders.Add(order);
try
{
_context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
// 處理併發衝突
ex.Entries.Single().Reload();
lastOrderNo = _context.Orders
.OrderByDescending(o => o.Id)
.Select(o=> o.OrderNo) .FirstOrDefault(); lastVersion = _context.Orders .OrderByDescending(o => o.Id) .Select(o => o.Version) .FirstOrDefault(); newOrderNo = GenerateNewOrderNo(lastOrderNo); order.OrderNo = newOrderNo; order.Version = lastVersion + 1; _context.SaveChanges(); } return newOrderNo; } private string GenerateNewOrderNo(string lastOrderNo) { // 生成新的單據號邏輯 // ... }
}
反思
EFCORE 和 行級鎖,如果提問者不知道這兩者的含義根本沒法問,就算問了,回答的東西,所以chatGPT對提問者也是有要求的
再沒有chatGPT以前,我們碼農如果遇到這個問題如何解決了?
很簡單,使用各種搜索引擎,或者詢問同行,搜集零碎的信息然後最終拼湊起來
程式員在有了chatGPT之後,有什麼變化?
顯而易見,縮短了搜索的時間
總結
其實不管是以前的面向搜索引擎編程,還是面向群友編程,其實都在暗中隱喻了程式員的未來——架構師
開發軟體應用,最終是為了人類某個行業提供多一種可選方式
(例如外賣,古代也有外賣,讓店小二提餐走路送去大戶人家家裡
後來有了馬車,單車,直到現在的摩托車,什麼變了?方式變了,最終目的並沒有改變
做開發其實也是一個道理,我們並不是做一個XX軟體去替代,而是為了原本的最終目的提供多一種方式,而程式員則是這多出來的一種方式的設計師,讓這個新的方式更加的容易被大眾接納和方便使用
要不然,我原本方式很簡單,為什麼要用你給我提供的方式呢?近些年開發行業也經常出現這種本末倒置的情況,很多碼農都不知道自己開發這些軟體應用的目的到底是為什麼,對於我們開發者而言
不管什麼技術,只是為了達成最終目的的手段,而不是最終目的
這也是我實在不喜歡背誦一些照本宣科的書面理論知識,而是更熱衷提出和發現程式的到設計思路
說了這麼多只是想說,程式員的未來肯定會是架構師,我們所有的技術積累我個人看來只是為了讓我們的思維從普通人轉換成程式員思維,而且我相信在未來,編程思維會如同吃飯一樣,成為每個人的必備