zoukankan      html  css  js  c++  java
  • 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次与数据库交互。

  • 相关阅读:
    Linux 多线程编程 实例 1
    面试题-链表反转c实现
    information_schema.TABLES
    mongodb遇到的错误
    MySQL优化的奇技淫巧之STRAIGHT_JOIN
    mongodb安装
    XtraBackup安装
    提高mysql千万级大数据SQL查询优化30条经验(Mysql索引优化注意)
    我用 TypeScript 语言的七个月
    Grunt之添加文件监视:Grunt-watch (已备份)
  • 原文地址:https://www.cnblogs.com/uncle_danny/p/5641742.html
Copyright © 2011-2022 走看看