NHibernate - Taille du lot
Dans ce chapitre, nous couvrirons la mise à jour de la taille du lot. La taille du lot vous permet decontrol the number of updates qui sortent en un seul aller-retour vers votre base de données pour les bases de données prises en charge.
La taille du lot de mise à jour a été définie par défaut à partir de NHibernate 3.2.
Mais si vous utilisez une version antérieure ou avez besoin d'ajuster votre application NHibernate, vous devriez regarder la taille du lot de mise à jour, qui est un paramètre très utile qui peut être utilisé pour ajuster les performances de NHibernate.
En fait, la taille du lot contrôle le nombre d'insertions à pousser dans un groupe vers une base de données.
Pour le moment, seuls SQL Server et Oracle prennent en charge cette option car le fournisseur de base de données sous-jacent doit prendre en charge le traitement par lots des requêtes.
Jetons un coup d'œil à un exemple simple dans lequel nous avons défini la taille du lot à 10, ce qui insérera 10 enregistrements dans un ensemble.
cfg.DataBaseIntegration(x => {
x.ConnectionString = "default";
x.Driver<SqlClientDriver>();
x.Dialect<MsSql2008Dialect>();
x.LogSqlInConsole = true;
x.BatchSize = 10;
});
Voici l'implémentation complète dans laquelle 25 enregistrements seront ajoutés à la base de données.
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();
}
}
}
}
Maintenant, exécutons votre application et vous voyez que toutes ces mises à jour passent au profileur NHibernate. Nous avons 26 allers-retours individuels vers la base de données 25 pour l'insertion et un pour récupérer la liste des étudiants.
Maintenant, pourquoi est-ce? La raison en est que NHibernate doit faire unselect scope identity car nous utilisons la stratégie de génération d'identifiant natif dans le fichier de mappage pour l'ID, comme indiqué dans le code suivant.
<?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>
Nous devons donc utiliser une méthode différente telle que la guid.combméthode. Si nous allons aller sur guid.comb, nous devons aller vers notre client et changer cela en unguid. Cela fonctionnera donc très bien. Passons maintenant du natif à guid.comb en utilisant le code suivant.
<?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>
C'est donc la base de données qui est chargée de générer ces identifiants. La seule façon dont NHibernate peut savoir quel ID a été généré était de le sélectionner immédiatement après. Sinon, si nous avons créé un lot d'étudiants, il ne pourra pas faire correspondre l'ID de l'étudiant qui a été créé.
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
}
}
Nous avons juste besoin de mettre à jour notre base de données. Supprimons la table des étudiants et créons une nouvelle table en spécifiant la requête suivante, alors allez dans l'explorateur d'objets SQL Server et cliquez avec le bouton droit sur la base de données et sélectionnez leNew Query… Option.
Il ouvrira l'éditeur de requête, puis spécifiera la requête suivante.
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)
);
Cette requête supprimera d'abord la table Student existante, puis créera une nouvelle table. Comme vous pouvez le voir, nous avons utiliséUNIQUEIDENTIFIER plutôt que d'utiliser une clé primaire entière comme ID.
Exécutez cette requête, puis accédez à la Designer view et vous verrez que maintenant l'ID est créé avec un identifiant unique comme indiqué dans l'image suivante.
Maintenant, nous devons supprimer l'ID du fichier program.cs, lors de l'insertion des données, car maintenant il générera le guids pour cela automatiquement.
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();
}
}
}
}
Maintenant, exécutez à nouveau l'application et jetez un œil au profileur NHibernate. Désormais, le profileur NHibernate, plutôt que de faire 26 allers-retours, n'en fera que quatre.
Il est inséré dix lignes dans le tableau, puis dix autres lignes, et plus tard les cinq autres. Et après la validation, il en a inséré un de plus pour récupérer tous les enregistrements.
Il a donc été divisé en groupes de dix, du mieux possible.
Donc, si vous faites beaucoup d'insertions, cela peut considérablement améliorer les performances d'insertion dans votre application, car vous pouvez les regrouper.
En effet, NHibernate attribue ces guides lui-même en utilisant le guid.comb algorithme, et il n'a pas besoin de s'appuyer sur la base de données pour ce faire.
L'utilisation de la taille du lot est donc un excellent moyen de l'ajuster.