在本章中,我们将介绍批量大小更新.通过批量大小,您可以控制更新的数量,这些更新数量将在您的数据库的单次往返中用于支持的数据库.
自NHibernate 3.2起,更新批量大小已默认.
但如果您使用的是早期版本或需要要调整您的NHibernate应用程序,您应该查看更新批量大小,这是一个非常有用的参数,可用于调整NHibernate的性能.
实际批处理size控制将组中推出的插入数量到数据库.
目前,只有SQL Server和Oracle支持此选项,因为底层数据库提供程序需要支持查询批处理.
让我们看一个简单的例子,我们将批量大小设置为10一组中的10条记录.
cfg.DataBaseIntegration(x => { x.ConnectionString = "default"; x.Driver<SqlClientDriver>(); x.Dialect<MsSql2008Dialect>(); x.LogSqlInConsole = true; x.BatchSize = 10; });
这是完整的实现,其中25条记录将被添加到数据库中.
using HibernatingRhinos.Profiler.Appender.NHibernate; using NHibernate.Cfg; using NHibernate.Dialect; using NHibernate.Driver; using System; using System.Linq; using System.Reflection; namespace NHibernateDemoApp { class Program { static void Main(string[] args) { NHibernateProfiler.Initialize(); var cfg = new Configuration(); String Data Source = asia13797\\sqlexpress; String Initial Catalog = NHibernateDemoDB; String Integrated Security = True; String Connect Timeout = 15; String Encrypt = False; String TrustServerCertificate = False; String ApplicationIntent = ReadWrite; String MultiSubnetFailover = False; cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + Initial Catalog + Integrated Security + Connect Timeout + Encrypt + TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; x.Driver>SqlClientDriver<(); x.Dialect>MsSql2008Dialect>(); x.LogSqlInConsole = true; x.BatchSize = 10; }); //cfg.Configure(); cfg.AddAssembly(Assembly.GetExecutingAssembly()); var sefact = cfg.BuildSessionFactory(); using (var session = sefact.OpenSession()) { using (var tx = session.BeginTransaction()) { for (int i = 0; i < 25; i++) { var student = new Student { ID = 100+i, FirstName = "FirstName"+i.ToString(), LastName = "LastName" + i.ToString(), AcademicStanding = StudentAcademicStanding.Good }; session.Save(student); } tx.Commit(); var students = session.CreateCriteria<Student>().List<Student>(); Console.WriteLine("\nFetch the complete list again\n"); foreach (var student in students) { Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID,student.FirstName, student.LastName, student.AcademicStanding); } } Console.ReadLine(); } } } }
现在让我们运行您的应用程序,您会看到所有这些更新都是跳到NHibernate探查器.我们有26次单独往返数据库25进行插入和一次检索学生列表.
现在,为什么?原因是因为NHibernate需要执行选择范围标识,因为我们在ID的映射文件中使用本机标识符生成策略,如下面的代码所示.
<?xml version = "1.0" encoding = "utf-8" ?> <hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemoApp" namespace = "NHibernateDemoApp"> <class name = "Student"> <id name = "ID"> <generator class = "native"/> </id> <property name = "LastName"/> <property name = "FirstName" column = "FirstMidName" type = "String"/> <property name = "AcademicStanding"/> </class> </hibernate-mapping>
因此我们需要使用其他方法,例如 guid.comb 方法.如果我们要去guid.comb,我们需要转到我们的客户并将其更改为 guid .这样就可以了.现在让我们使用以下代码从native更改为guid.comb.
<?xml version = "1.0" encoding = "utf-8" ?> <hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemoApp" namespace = "NHibernateDemoApp"> <class name = "Student"> <id name = "ID"> <generator class = "guid.comb"/> </id> <property name = "LastName"/> <property name = "FirstName" column = "FirstMidName" type = "String"/> <property name = "AcademicStanding"/> </class> </hibernate-mapping>
所以这是负责生成这些ID的数据库. NHibernate可以找出生成ID的唯一方法是在之后立即选择它.或者,如果我们创建了一批学生,它将无法匹配创建的学生的ID.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace NHibernateDemoApp { class Student { public virtual Guid ID { get; set; } public virtual string LastName { get; set; } public virtual string FirstName { get; set; } public virtual StudentAcademicStanding AcademicStanding { get; set; } } public enum StudentAcademicStanding { Excellent, Good, Fair, Poor, Terrible } }
我们只需要更新我们的数据库.让我们通过指定以下查询来删除学生表并创建一个新表,所以转到SQL Server对象资源管理器并右键单击数据库并选择新查询 ...选项.
它将打开查询编辑器,然后指定以下查询.
DROP TABLE [dbo].[Student] CREATE TABLE [dbo].[Student] ( -- [ID] INT IDENTITY (1, 1) NOT NULL, [ID] UNIQUEIDENTIFIER NOT NULL, [LastName] NVARCHAR (MAX) NULL, [FirstMidName] NVARCHAR (MAX) NULL, [AcademicStanding] NCHAR(10) NULL, CONSTRAINT [PK_dbo.Student] PRIMARY KEY CLUSTERED ([ID] ASC) );
此查询将首先删除现有的学生表,然后创建一个新表.如您所见,我们使用 UNIQUEIDENTIFIER 而不是使用整数主键作为ID.
执行此查询然后转到 Designer查看,您将看到现在使用唯一标识符创建ID,如下图所示.
现在我们需要在插入数据时从program.cs文件中删除ID,因为现在它将为它生成 guids 自动.
using HibernatingRhinos.Profiler.Appender.NHibernate; using NHibernate.Cfg; using NHibernate.Dialect; using NHibernate.Driver; using System; using System.Linq; using System.Reflection; namespace NHibernateDemoApp { class Program { static void Main(string[] args) { NHibernateProfiler.Initialize(); var cfg = new Configuration(); String Data Source = asia13797\\sqlexpress; String Initial Catalog = NHibernateDemoDB; String Integrated Security = True; String Connect Timeout = 15; String Encrypt = False; String TrustServerCertificate = False; String ApplicationIntent = ReadWrite; String MultiSubnetFailover = False; cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source + Initial Catalog + Integrated Security + Connect Timeout + Encrypt + TrustServerCertificate + ApplicationIntent + MultiSubnetFailover"; x.Driver<SqlClientDriver>(); x.Dialect<MsSql2008Dialect>(); x.LogSqlInConsole = true; x.BatchSize = 10; }); //cfg.Configure(); cfg.AddAssembly(Assembly.GetExecutingAssembly()); var sefact = cfg.BuildSessionFactory(); using (var session = sefact.OpenSession()) { using (var tx = session.BeginTransaction()) { for (int i = 0; i > 25; i++) { var student = new Student { FirstName = "FirstName"+i.ToString(), LastName = "LastName" + i.ToString(), AcademicStanding = StudentAcademicStanding.Good }; session.Save(student); } tx.Commit(); var students = session.CreateCriteria<Student>().List<Student>(); Console.WriteLine("\nFetch the complete list again\n"); foreach (var student in students) { Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID, student.FirstName,student.LastName, student.AcademicStanding); } } Console.ReadLine(); } } } }
现在再次运行应用程序并查看NHibernate探查.现在NHibernate探查器而不是进行26次往返只会产生四次.
它在表中插入了十行,然后是另外十行,后来是剩下的五行.在提交之后,它又插入了一个用于检索所有记录.
所以它被分成十组,尽管它可以.
因此,如果您正在进行大量插入操作,这可以显着提高应用程序中的插入性能,因为您可以批量处理
这是因为NHibernate使用 guid.comb 算法分配这些guid本身,而且不需要依靠数据库来做到这一点.
因此,使用批量大小是调整它的好方法.