Entity Framework Core 使用HiLo生成主鍵

来源:http://www.cnblogs.com/tdfblog/archive/2017/11/23/entity-framework-core-hilo.html
-Advertisement-
Play Games

HiLo是在NHiernate中生成主鍵的一種方式,不過現在我們可以在Entity Framework Core中使用。所以在這篇內容中,我將向您在如何使用HiL在Entity Framework Core生成主鍵。 ...


HiLo是在NHibernate中生成主鍵的一種方式,不過現在我們可以在Entity Framework Core中使用。所以在這篇內容中,我將向您在介紹如何在Entity Framework Core中使用HiLo生成主鍵。

什麼是Hilo?

HiLo是High Low的簡寫,翻譯成中文叫高低位模式。

HiLo是由“Hi”和“Lo”兩部分生成主鍵的一種模式。“Hi”部分來自資料庫,“Lo”部分在記憶體中生成以創建唯一值。請記住,“Lo”是一個範圍數字,如0-100。因此,當“Hi”部分用完“Lo”範圍時,再次進行資料庫調用以獲得下一個“Hi數字”。所以HiLo模式的優點在於您預先可以知道主鍵的值,而不用每次都與數庫據發生交互

總結有以下四點:

  1. “Hi”部分由資料庫分配,兩個併發請求保證得到唯一的連續值;
  2. 一旦獲取“Hi”部分,我們還需要知道“incrementSize”的值(“Lo”條目的數量);
    “Lo”取的範圍:[0,incrementSize];
  3. 標識範圍的公式是:(Hi - 1) * incrementSize) + 1(Hi - 1) * incrementSize) + incrementSize)
  4. 當所有“Lo”值使用完時,需要重新從資料庫中取出一個新的“Hi”值,並將“Lo”部分重置為0。

在這裡演示在兩個併發事務中的例子,每個事務插入多個實體:

Sql Server 序列

在EF Core中使用HiLo生成主鍵,我們還需要瞭解Sql Server中一個概念序列(Sequence)

序列是在SQL Server 2012中引入的(不過Oracle很早就已經實現了http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_6015.htm)。序列是用戶定義的對象,它根據創建的屬性生成一系列數值。它與 Identity 列相似,但它們之間有很多不同之處。例如,

  • 序列用於生成資料庫範圍的序列號;
  • 序列不與一個表相關聯,您可以將其與多個表相關聯;
  • 它可以用於插入語句來插入標識值,也可以在T-SQL腳本中使用。

創建序列示例的SQL語句:

Create Sequence [dbo].[Sequence_Test] 
As [BigInt]         --整數類型
Start With 1        --起始值
Increment By 1      --增量值
MinValue 1          --最小值
MaxValue 9999999    --最大值
Cycle               --達到最值迴圈 [ CYCLE | NO CYCLE ]
Cache  5;           --每次取出5個值緩存使用 [ CACHE [<常量>] | NO CACHE ]

使用示例:

Create Table #T(Id BigInt Primary Key,[Time] DateTime);

Insert Into #T
            ( Id , Time )
Values      ( NEXT VALUE FOR [dbo].[Sequence_Test] , -- Id - bigint
              GetDate()  -- Time - datetime
              )
Go 10


Select * From #T

查詢結果:

Id Time
1 2017-11-23 16:46:50.613
2 2017-11-23 16:46:50.643
3 2017-11-23 16:46:50.667
4 2017-11-23 16:46:50.677
5 2017-11-23 16:46:50.687
6 2017-11-23 16:46:50.697
7 2017-11-23 16:46:50.707
8 2017-11-23 16:46:50.717
9 2017-11-23 16:46:50.730
10 2017-11-23 16:46:50.740

關於序列更多的內容,可以查閱如下資料:

使用HiLo生成主鍵

讓我們看看如何使用HiLo在Entity Framework Core中生成主鍵。

為了演示,我們創建了兩個沒有關係的實體。

    public class Category
    {
        public int CategoryID { get; set; }
        public string CategoryName { get; set; }
    }
    
    public class Product
    {
        public int ProductID { get; set; }
        public string ProductName { get; set; }
    }

請記住,EF Core按慣例配置一個名為Id<type name>Id作為實體的主鍵屬性。現在我們需要創建我們的DBContext,在這裡我們創建SampleDBContext.cs類:

public class SampleDBContext : DbContext
{
    public SampleDBContext()
    {
        Database.EnsureDeleted();
        Database.EnsureCreated();
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionbuilder)
    {
            var sqlConnectionStringBuilder = new SqlConnectionStringBuilder {
                DataSource = "****",
                InitialCatalog = "EFSampleDB",
                UserID = "sa",
                Password = "***"
            };
            optionsBuilder.UseSqlServer(sqlConnectionStringBuilder.ConnectionString);

    }

    protected override void OnModelCreating(ModelBuilder modelbuilder)
    {
        modelbuilder.ForSqlServerUseSequenceHiLo("DBSequenceHiLo");
    }

    public DbSet<Product> Products { get; set; }
    public DbSet<Category> Categories { get; set; }
}
  • SampleDBContext構造函數初始化資料庫,類型於EF 6中的DropCreateDatabaseAlways
  • OnConfiguring() 方法用於配置資料庫鏈接字元串;
  • OnModelCreating方法用於定義實體模型。要定義HiLo序列,請使用ForSqlServerUseSequenceHiLo擴展方法。您需要提供序列的名稱。

運行應用程式,您應該在創建“EFSampleDB”資料庫中看到Product表、Category表和DBSequenceHiLo序列。

以下是創建DBSequenceHiLo的腳本。

Create Sequence [dbo].[DBSequenceHiLo] 
 As [BigInt]
 Start With 1
 Increment By 10
 MinValue -9223372036854775808
 MaxValue 9223372036854775807
 Cache 
Go

正如你所看到的,它從1開始,遞增是10。

現在向資料庫中添加一些數據。以下代碼首先添加3個Category實體和調用SaveChanges(),然後添加3個Product實體並調用SaveChanges()

    using (var dataContext = new SampleDBContext())
    {
        dataContext.Categories.Add(new Category() { CategoryName = "Clothing" });
        dataContext.Categories.Add(new Category() { CategoryName = "Footwear" });
        dataContext.Categories.Add(new Category() { CategoryName = "Accessories" });
        dataContext.SaveChanges();
        dataContext.Products.Add(new Product() { ProductName = "TShirts" });
        dataContext.Products.Add(new Product() { ProductName = "Shirts" });
        dataContext.Products.Add(new Product() { ProductName = "Causal Shoes" });
        dataContext.SaveChanges();
    }

當這個代碼第一次被執行,Clothing 實體通過Add方法增加到DBContext時,就會向資料庫調用獲取序列的值,我們也可以通過SQL Server Profiler來驗證它。

次調用dataContext.SaveChanges()時,3個Category實體將被保存。查看執行的SQL語句。主鍵值已經被生成,序列值的獲取也只執行了一次。

即使插入3個Product實體,序列值也不會從資料庫中獲取。只有當插入10條記錄(Lo部分耗盡)時,才會向資料庫調用獲得下一個(Hi部分)序列值。

向HiLo運用到單個實體

上面的代碼兩個表共用一個HiLo序列。如果您只想針對一個特定的表,那麼您可以使用下麵的代碼。

    modelbuilder.Entity<Category>().
            Property(o => o.CategoryID).ForSqlServerUseSequenceHiLo();

這段代碼將創建一個預設名稱為“EntityFrameworkHiLoSequence”的新序列,因為沒有指定名字。您也可以定義多個HiLo序列。例如:

    protected override void OnModelCreating(ModelBuilder modelbuilder)
    {
        modelbuilder.ForSqlServerUseSequenceHiLo("DBSequenceHiLo");
        modelbuilder.Entity<Category>()
                .Property(o => o.CategoryID).ForSqlServerUseSequenceHiLo();
    }

在資料庫中,將創建兩個序列。Category實體將使用EntityFrameworkHiLoSequence序號,所有其它實體使用DBSequenceHiLo序列。

配置HiLo序列

ForSqlServerHasSequence擴展方法不能更改起始值和增量值的選項。但是,有一種方法來定義這些選項。首先,使用HasSequence方法定義序列的StartAtIncrementBy選項,然後再使用ForSqlServerUseSequenceHiLo()擴展方法,要保持序列的名稱一致。例如:

    modelbuilder.HasSequence<int>("DBSequenceHiLo")
                      .StartsAt(1000).IncrementsBy(5);
    modelbuilder.ForSqlServerUseSequenceHiLo("DBSequenceHiLo");

在這種情況下,生成DBSequenceHiLo的腳本如下。

CREATE SEQUENCE [dbo].[DBSequenceHiLo] 
 AS [int]
 START WITH 1000
 INCREMENT BY 5
 MINVALUE -2147483648
 MAXVALUE 2147483647
 CACHE 
GO

所以當我們執行相同的代碼插入3個Category實體,那麼主鍵的值將從1000開始。

而且由於IncrementBy選項設置為“5”,所以當在上下文中添加第6個插入時,將進行資料庫調用以獲得下一個序列值。以下是插入3個Category實體然後插入3個的Product實體時SQL Server profiler的屏幕截圖,您可以看到資料庫調用獲取序列的下一個值的次數是2次。

如果您對在Entity Framework Core中使用HiLo生成主鍵感興趣,不防自己動手測試一下。

參考資料:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 寫這篇沒有參考任何文章,只是寫下自己一路使用的體會 linux與windows給我的感覺有點像flask之於django.linux只有一個小而強大的內核,各種應用軟體配置自由,就連桌面也有不同的可供選擇。 linux的歷史就不介紹了,百度都有。說一下各個發行版: 發行版之間的區別說白了就是軟體的搭 ...
  • 上面的代碼是我們在使用繼承時,子類和父類的構造函數的寫法。構造方法能否被繼承,我覺得應該這樣理解: 父類是對子類的抽象,也就是說父類和子類可以合併寫成一個類,合併後的類寫出來的構造函數,不僅會包含子類的構造函數的內容,還會包含父類的構造函數的內容,所以我覺得這裡不能看成是子類繼承父類的構造函數,看成 ...
  • Q:i want to pass my List as parameter using my eventpublic event EventHandler _newFileEventHandler; List _filesList = new List();public void startList... ...
  • 現在說一下程式處理部分,有點長 本來是想做針對doc和docx的模板兩個版本, 後來想到可以在生成的時候saveas里設置格式, 所以此版只支持對docx的模板處理, 想要doc的情況可以選擇生成格式為doc的. 上代碼: public class WordHelper { private Word ...
  • 既然是模板就少不了各種標記和配置. 這裡主要用到了word的書簽功能. 打開word按ctrl+shift+F5, 打開書簽功能 如下圖 如果所示, 可以選中word中的一個區域然後按ctrl+shift+F5, 對此部分添加一個書簽 是否理解為這樣是為這部分區域添加了指針? 根據圖中的操作就可以明 ...
  • 還是以學生、語文、數學、分數為例吧, 感覺這個和helloworld都有一拼了. 造一張表如下, 整張報表就圍繞這個表轉圈了, 順便說下就是名字如有雷同純屬巧合 新建個存儲過程 ALTER PROCEDURE [dbo].[StudentReport] AS BEGIN select 學期,max( ...
  • using System.Linq; List<string> ListA = new List<string>(); List<string> ListB = new List<string>(); List<string> ListResult = new List<string>(); Lis ...
  • 經常遇到這樣的需求, 生成Word格式的報告, 而不是單純的一張表格的報表. 就像體檢報告一樣. 數據來源部分決定採用一個存儲過程返回Dataset的方式, 整張報告的數據來源於此Dataset的多個Datatable. 首先通過配置文件遍歷Dataset生成Word文檔, 但這就意味著要配置的內容 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...