Учебники

NHibernate — размер партии

В этой главе мы рассмотрим обновление размера партии. Размер пакета позволяет вам контролировать количество обновлений, которые выходят за одну поездку в вашу базу данных для поддерживаемых баз данных.

  • Размер пакета обновления по умолчанию установлен на NHibernate 3.2.

  • Но если вы используете более раннюю версию или вам нужно настроить приложение NHibernate, вы должны посмотреть на размер пакета обновления, который является очень полезным параметром, который можно использовать для настройки производительности NHibernate.

  • На самом деле размер пакета определяет, сколько вставок нужно вставить в группу в базу данных.

  • На данный момент только SQL Server и Oracle поддерживают эту опцию, поскольку базовый поставщик баз данных должен поддерживать пакетирование запросов.

Размер пакета обновления по умолчанию установлен на NHibernate 3.2.

Но если вы используете более раннюю версию или вам нужно настроить приложение NHibernate, вы должны посмотреть на размер пакета обновления, который является очень полезным параметром, который можно использовать для настройки производительности NHibernate.

На самом деле размер пакета определяет, сколько вставок нужно вставить в группу в базу данных.

На данный момент только 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 должен выполнить выборку идентификатора области, поскольку мы используем стратегию генерирования собственного идентификатора в файле сопоставления для идентификатора, как показано в следующем коде.

<?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 . Так что это будет работать нормально. Теперь давайте перейдем с нативного на 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>

Так что именно база данных отвечает за генерацию этих идентификаторов. Единственный способ, которым NHibernate может узнать, какой идентификатор был сгенерирован, — это сразу же выбрать его. Или же, если мы создали группу студентов, она не сможет соответствовать идентификатору студента, который был создан.

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, а не целочисленный первичный ключ в качестве идентификатора.

Выполните этот запрос, а затем перейдите в представление Designer, и вы увидите, что теперь идентификатор создается с уникальным идентификатором, как показано на следующем рисунке.

Дизайнерский вид

Теперь нам нужно удалить идентификатор из файла program.cs при вставке данных, потому что теперь он автоматически сгенерирует для него направляющие .

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 Круглые поездки

Он вставляет десять строк в таблицу, затем еще десять строк, а затем оставшиеся пять. И после фиксации он вставил еще одну для извлечения всех записей.

Таким образом, это разделено на группы по десять, насколько это возможно.

Поэтому, если вы делаете много вставок, это может значительно улучшить производительность вставки в вашем приложении, потому что вы можете пакетировать ее.

Это связано с тем, что NHibernate сам назначает эти направляющие с помощью алгоритма guid.comb , и для этого ему не нужно полагаться на базу данных.

Таким образом, использование размера пакета — отличный способ настроить его.