📅  最后修改于: 2020-11-19 05:35:42             🧑  作者: Mango
在本章中,我们将介绍批量大小的更新。批处理大小允许您控制在单次往返中为支持的数据库到数据库的更新数量。
自NHibernate 3.2起,更新批处理大小已被默认设置。
但是,如果您使用的是较早版本,或者需要调整NHibernate应用程序,则应查看更新批处理大小,这是一个非常有用的参数,可用于调整NHibernate的性能。
实际上,批大小控制着将一组插入到数据库中的插入次数。
目前,只有SQL Server和Oracle支持此选项,因为基础数据库提供程序需要支持查询批处理。
让我们看一个简单的示例,在该示例中,我们将批处理大小设置为10,这将在一组中插入10条记录。
cfg.DataBaseIntegration(x => {
x.ConnectionString = "default";
x.Driver();
x.Dialect();
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>SqlClientDriverMsSql2008Dialect>();
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().List();
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 profiler。我们有26次往返数据库25的往返行程,其中一次是往返旅行,一次是检索学生名单。
现在,为什么呢?原因是因为NHibernate需要做一个选择范围标识,因为我们在映射文件中为ID使用本地标识符生成策略,如以下代码所示。
因此,我们需要使用其他方法,例如guid.comb方法。如果要转到guid.comb,则需要转到客户并将其更改为guid 。这样就可以了。现在,使用以下代码将本机更改为guid.comb。
因此,负责生成这些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
}
}
我们只需要更新我们的数据库。通过指定以下查询,让我们删除Student表并创建一个新表,因此,转到SQL Server Object Explorer,右键单击数据库,然后选择New Query …选项。
它将打开查询编辑器,然后指定以下查询。
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,因为现在它将自动为其生成向导。
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();
x.Dialect();
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().List();
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 Profiler。现在,NHibernate Profiler不会进行26次往返,而只能进行4次。
它在表中插入了十行,然后又插入了十行,之后又插入了其余五行。提交后,它又插入了一个以检索所有记录。
因此,将其尽可能分成十组。
因此,如果您要执行大量插入操作,这可以极大地提高应用程序中插入操作的性能,因为您可以对其进行批量处理。
这是因为NHibernate使用guid.comb算法自己分配了这些guid,而不必依靠数据库来执行此操作。
因此,使用批处理大小是调整它的好方法。