狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

【C#】使用 NewId 庫在 .NET 中生成可排序的唯一ID

admin
2024年4月9日 22:21 本文熱度 683

摘要

在本文中,我們將探討為什么我們在 .NET 中可能需要可排序的唯一ID,以及如何使用 NewId NuGet 包來創建它們。

原文 Generate Sortable Unique IDs With the NewId Library in .NET 由 Ivan Gechev 撰寫。


在本文中,我們將探討為什么我們在 .NET 中可能需要可排序的唯一ID,以及如何使用 NewId NuGet 包來創建它們。

要下載本文的源代碼,您可以訪問我們的 GitHub 倉庫

為什么我們在 .NET 中需要可排序的唯一ID

我們都知道,生成項目中實體的ID有兩種主要方法:要么是 int,要么是 Guid(全局唯一標識符)值。但這兩種方法都有它們的問題。讓我們在一個處理客戶訂單的 API 中探討一下。

整數作為主鍵

首先,讓我們看看整數作為主鍵:

public class Order
{
    public int Id { get; set; }
    public required string CustomerName { get; set; }
    public required IEnumerable<string> Products { get; set; }
    public required decimal TotalAmount { get; set; }
}

我們創建了一個 Order 類并使用 int 作為ID。

采用這種方法,我們將ID生成工作交給數據庫提供商。好處是我們得到了短小、美觀、連續的ID。但,使用數據庫生成的主鍵,我們遇到一個主要缺點 —— 我們的應用程序變得更難擴展。處理大量的插入語句迫使我們的數據庫不斷使用鎖來處理生成新的主鍵。

在幾個不同的數據庫中存儲實體并維護唯一的 int ID也幾乎是不可能的。另外,我們可能會向我們的競爭對手泄露敏感信息 - 我們是否希望擁有連續的ID并讓別人確切知道我們有多少訂單?

全局唯一標識符作為主鍵

另一種流行的方法是使用 Guid 值:

public class OrderService(IUnitOfWork unitOfWork) : IOrderService
{
    public async Task<OrderDto> CreateAsync(
        OrderForCreationDto orderForCreationDto,
        CancellationToken cancellationToken = default
)

    {
        var order = new Order
        {
            Id = Guid.NewGuid(),
            CustomerName = orderForCreationDto.CustomerName,
            Products = orderForCreationDto.Products,
            TotalAmount = orderForCreationDto.TotalAmount,
        };
        unitOfWork.OrderRepository.Insert(order);
        await unitOfWork.SaveChangesAsync(cancellationToken);
        return new OrderDto
        {
            Id = order.Id,
            CustomerName = order.CustomerName,
            Products = order.Products,
            TotalAmount = order.TotalAmount,
        };
    }
    // 省略以簡潔
}

我們首先將 Order 的標識從 int 變更為 Guid,然后我們創建了 OrderService 類。我們的項目基于 Onion 架構,所以我們的服務使用一個 Dto 對象,處理它,并使用倉庫將實體插入數據庫。

采用這種方法,OrderService 類負責生成主鍵值。最大的好處在于我們可以使用 Guid.NewGuid() 輕松獲得唯一ID。擁有唯一但隨機的ID使我們的應用擴展到幾個數據庫變得非常容易。但這也是它們最大的問題:它使我們的數據基于主鍵單獨排序變得不可能,并可能導致潛在的索引問題。這種類型的主鍵在數據庫中存儲時也會占用四倍于常規整數的空間。

這就是 NewId 庫發揮作用的地方。通過使用它,我們結合了 int 和 Guid 主鍵的優點,同時消除了一些缺點。

NewId 庫是什么

NewId 庫是一個 NuGet 包,我們可以用它來生成唯一但可排序的ID。 它基于現已退役的 Snowflake:X(前 Twitter)內部服務,用于生成可排序的唯一主鍵。NewId 是分布式應用框架 MassTransit 的一部分,旨在解決 int 和 Guid 標識符存在的問題。其目的是提供一種在大規模下生成唯一且可排序ID的方法。

該包基于三個事物生成ID - 時間戳、工作ID和進程ID。這樣我們最終得到的是雖然唯一但仍可排序的ID,并且當我們的應用和數據庫有多個實例時不會發生沖突。

這個材料對你有用嗎?考慮訂閱并免費獲取 ASP.NET Core Web API 最佳實踐 電子書!

在我們開始生成ID之前,我們需要安裝 NewId 包:

dotnet add package NewId

使用 dotnet add package 命令,我們安裝了這個庫。

現在我們已經準備好了,讓我們開始使用這個包來生成ID。

要生成我們的可排序唯一ID,我們需要使用 NewId 類。它位于 MassTransit 命名空間中,有三個方法。

首先是 Next() 方法 - 生成一個新的 NewId 類實例:

00070000-ac11-0242-3d9b-08dc45bed613
00070000-ac11-0242-c9d3-08dc45bed614
00070000-ac11-0242-cafd-08dc45bed614
00070000-ac11-0242-cb2e-08dc45bed614
00070000-ac11-0242-cb69-08dc45bed614

接下來,NextGuid() 方法 - 生成一個新的 Guid 值:

00070000-ac11-0242-df20-08dc45bed614
00070000-ac11-0242-0c11-08dc45bed615
00070000-ac11-0242-0d30-08dc45bed615
00070000-ac11-0242-0d46-08dc45bed615
00070000-ac11-0242-0d58-08dc45bed615

最后,NextSequentialGuid() 方法 - 生成一個新的順序 Guid 值:

08dc45be-d615-19b5-0242-ac1100070000
08dc45be-d615-1b01-0242-ac1100070000
08dc45be-d615-1b46-0242-ac1100070000
08dc45be-d615-1b66-0242-ac1100070000
08dc45be-d615-1ba4-0242-ac1100070000

我們可以看到,使用 Next() 和 NextGuid() 方法,我們得到相同的模式,其中 NextSequentialGuid() 方法有稍微不同的模式。后兩種方法返回一個 Guid 值,我們的類不需要修改,但如果我們選擇 Next() 方法,我們將需要更改我們 Order 類的ID類型。

讓我們使用其中一個:

public class OrderService(IUnitOfWork unitOfWork) : IOrderService
{
    public async Task<OrderDto> CreateAsync(
        OrderForCreationDto orderForCreationDto,
        CancellationToken cancellationToken = default
)

    {
        var order = new Order
        {
            Id = NewId.NextSequentialGuid(),
            CustomerName = orderForCreationDto.CustomerName,
            Products = orderForCreationDto.Products,
            TotalAmount = orderForCreationDto.TotalAmount,
        };
        unitOfWork.OrderRepository.Insert(order);
        await unitOfWork.SaveChangesAsync(cancellationToken);
        return new OrderDto
        {
            Id = order.Id,
            CustomerName = order.CustomerName,
            Products = order.Products,
            TotalAmount = order.TotalAmount,
        };
    }
    // 省略以簡潔
}

在我們的 OrderService 類中,我們生成ID的地方,我們用 NewId.NextSequentialGuid() 方法替換了 Guid.NewGuid() 方法。這是我們唯一需要做的改變。

讓我們運行我們的 API 并添加一些訂單:

[
  {
    "id": "08dc45c0-b5b5-0d5d-5811-22b038790000",
    "customerName": "Marcel Waters",
    "products": ["Piano"],
    "totalAmount": 599.99
  },
  {
    "id": "08dc45c0-d6f4-fbed-5811-22b038790000",
    "customerName": "Elizabeth Doyle",
    "products": ["Vase", "Mirror", "Blanket"],
    "totalAmount": 49.39
  },
  {
    "id": "08dc45c0-f143-a9f9-5811-22b038790000",
    "customerName": "Rayford Lopez",
    "products": ["Headphones", "Microphone"],
    "totalAmount": 86.06
  }
]

我們可以看到,我們的實體現在擁有唯一但不完全隨機的標識符,這些標識符可以排序。

何時不應使用 NewId 庫生成可排序的唯一ID

雖然 NewId 庫為我們提供了生成可排序唯一ID的便利,但在一些場景下我們應該避免使用它們。至關重要的是要記住,我們生成的ID具有一定程度的可預測性。當你知道它們的創建算法時,它們可以被猜測。

因此,當不可預測性和安全性至關重要時,最好不要使用 NewId 生成的ID。我們不應該在需要高度保密性的敏感信息如密碼、安全令牌或任何其他數據上使用這樣的ID。如果我們在這樣的場景下依賴 NewId 庫,我們可能會危及我們應用程序的安全。這可能會使它們暴露于漏洞和未經授權的訪問中。因此,當我們的應用程序在安全上有重要需求時,需要格外小心。

結論

在本文中,我們探討了在作為主鍵時,整數和全局唯一標識符的限制,以及需要一種新方法的原因。NewId NuGet 包為我們提供了一個解決方案,提供了基于時間戳、工作ID和進程ID組合的唯一、可排序的ID。通過使用 NewId 庫,我們獲得了 int 和 Guid 主鍵的好處,同時減少了它們的缺點。這使我們能夠輕松實現可擴展性、有效的索引,并提高我們的數據組織。所有這些最終增強了我們的應用程序的健壯性和功能。


該文章在 2024/4/9 22:21:59 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved