NHibernate系列文章十三:NHibernate批量更新


摘要

對於批量插入和批量修改數據,通過設置NHibernate配置文件的BatchSize屬性,可以大量減少NHibernate與數據庫交互的次數。

1. Batch屬性介紹

設置了BatchSize屬性后,NHibernate將對批量的Insert/Update操作進行自動分組,按分組提交到數據庫,大量減少了與數據庫交互的次數。

NHibernate目前只支持對SQL Server數據庫和Oracle數據庫的批量Insert/Update操作進行BatchSize優化。

對於Insert操作,NHibernate只能對主鍵數據類型是UNIQUEIDENTIFIER的表提供BatchSize優化。

1)IDENTITY類型主鍵

在上一篇文章中,Customer表主鍵類型是IDENTITY類型的。

程序演示

修改SessionFactory屬性,添加x.BatchSize = 10的配置。

 1         public static ISessionFactory SessionFactory
 2         {
 3             get
 4             {
 5                 if (_sessionFactory == null)
 6                 {
 7                     var cfg = new Configuration();
 8                     cfg.DataBaseIntegration(x=> {
 9                         x.BatchSize = 10;
10                     });
11                     cfg.Configure();
12                     _sessionFactory = cfg.BuildSessionFactory();
13                 }
14                 return _sessionFactory;
15             }
16         }

修改Main函數

 1         static void Main(string[] args)
 2         {
 3             HibernatingRhinos.Profiler.Appender.NHibernate.NHibernateProfiler.Initialize();
 4 
 5             using (var session = SessionFactory.OpenSession())
 6             {
 7                 for (int i = 0; i < 25; i++)
 8                 {
 9                     var customer = new Customer
10                     {
11                         FirstName = "FirstName" + i,
12                         LastName = "LastName" + i,
13                         MemberSince = new DateTime(2012, 1, 1)
14                     };
15                     session.Save(customer);
16                 }
17                 session.Flush();
18                 Console.WriteLine("fetch the complete list");
19                 var list = session.CreateCriteria<Customer>().List<Customer>();
20                 foreach (Customer customer in list)
21                 {
22                     Console.WriteLine("{0} {1}", customer.FirstName,customer.LastName);
23                 }
24             }
25 
26             Console.WriteLine("Completed");
27             Console.ReadLine();
28         }

打開NHibernate Profile,清空Session,執行程序,得到結果

監控到NHibernate執行了26次SQL語句,25次Insert語句和1次Select語句。

這是因為,雖然配置了BatchSize=10,但是Customer表的主鍵列的生成策略是Identity,每次Insert操作完成后都要計算下一條新記錄的主鍵值,因此BatchSize沒辦法對其進行分組優化。

選擇一條Insert監控數據,在Detail欄中看到執行了select SCOP_IDENTITY()語句。

2)UNIQUEIDENTIFIER類型主鍵

刪除Customer表,用UNIQUEIDENTIFIER主鍵重建Customer表。

重建Customer表的SQL語句。

 1 CREATE TABLE [dbo].[Customer](
 2     --[Id] [int] IDENTITY(1,1) NOT NULL,
 3     Id UNIQUEIDENTIFIER NOT NULL,  4     [FirstName] [nvarchar](100) NOT NULL,
 5     [LastName] [nvarchar](100) NOT NULL,
 6     [Points] [int] NULL,
 7     [HasGoldStatus] [bit] NULL,
 8     [MemberSince] [date] NULL,
 9     [CreditRating] [nchar](20) NULL,
10     [AverageRating] [decimal](18, 4) NULL,
11     [Street] [nvarchar](100) NULL,
12     [City] [nvarchar](100) NULL,
13     [Province] [nvarchar](100) NULL,
14     [Country] [nvarchar](100) NULL,
15  CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED 
16 (
17     [Id] ASC
18 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
19 ) ON [PRIMARY]

修改Customer類,Id屬性類型改成了Guid。

 1     public class Customer
 2     {
 3         public virtual Guid Id { get; set; }  4         public virtual string FirstName { get; set; }
 5         public virtual string LastName { get; set; }
 6         public virtual double AverageRating { get; set; }
 7         public virtual int Points { get; set; }
 8         public virtual bool HasGoldStatus { get; set; }
 9         public virtual DateTime MemberSince { get; set; }
10         public virtual CustomerCreditRating CreditRating { get; set; }
11         public virtual string Street { get; set; }
12         public virtual string City { get; set; }
13         public virtual string Province { get; set; }
14         public virtual string Country { get; set; }
15     }

修改Customer.hbm.xml文件,將Id的generator class改成了guid.comb。

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateDemoApp" namespace="NHibernateDemoApp">
  <class name="Customer" table="Customer">
    <id name="Id">
      <generator class="guid.comb"/>
    </id>
    <property name="FirstName" not-null="true"/>
    <property name="LastName" not-null ="true"/>
    <property name="AverageRating"/>
    <property name="Points"/>
    <property name="HasGoldStatus"/>
    <property name="MemberSince"/>
    <property name="CreditRating" type="CustomerCreditRating"/>
    <property name="Street"/>
    <property name="City"/>
    <property name="Province"/>
    <property name="Country"/>
  </class>
</hibernate-mapping>

清空NHibernate Profile的Session,執行程序,得到結果。

NHibernate只與數據庫交互了四次,三次Insert,一次Select。因為表的主鍵類型是UNIQUEIDENTIFIER,每次Insert記錄時NHibernate自動生成新記錄主鍵值,不需要數據庫計算下一條記錄的主鍵值。

設置了BatchSize=10,NHibernate將25次Insert操作自動分成三組,第一組10條Insert語句,第二組10條Insert語句,第三組5條Insert語句,再加上最后的一次查詢語句,一共是4次與數據庫交互。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM