Для выполнения bulk операций над базой данных в NHibernate есть специальная StatelessSession. Интерфейс данного объекта отличается от стандартного Session, у него нет методов Save, SaveOrUpdate и т.д., зато есть Insert, Update, Delete.
Особенность StatelessSession в том, что она не следит за сохранёнными объектами, значит это следующее, рассмотрим следующий пример кода:
using(var transaction = Session.BeginTransaction())
{
var someObject = Session.Get<SomeObject>(id);
someObject.SomeProperty = "some new value";
transaction.Commit();
}
В результате выполнения этого кода someObject будет обновлен не только в вашем приложении, но в и базе данных.
За подобное приходится платить производительностью, в частности именно это стало причиной того, что на OrmBattle Nhibernate получает далеко не самые лучшие отметки (кстати по этому поводу есть довольно хороший ответ от Ayende).
А теперь перейдем к основной теме. Показать хотелось бы следующее:
ISessionFactory sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString("connString")
.AdoNetBatchSize(40)) // important!
.Mappings(x=>x.FluentMappings.AddFromAssemblyOf<TestHilo>())
.BuildSessionFactory();
IStatelessSession session = sessionFactory.OpenStatelessSession();
for (int i = 0; i < 60; i++)
{
var testHilo = new TestHilo
{
Field1 = "field" + i,
Field2 = i
};
session.Insert(testHilo);
}
session.Dispose();
Данный код должен вставить 60 записей в базу. На самом же деле вставится только 40. Происходит это из-за установленного AdoNetBatchSize (подробнее об этом в предыдущем посте). Когда это обнаружилось первое что захотелось сделать это вызвать session.Flush(). Но у StatelessSession нет такого метода :).
В общем решением будет следующее – выполнять данный цикл в рамках одной транзацкии:
using (ITransaction transaction = session.BeginTransaction())
{
for (int i = 0; i < 60; i++)
{
var testHilo = new TestHilo
{
Field1 = "field" + i,
Field2 = i
};
session.Insert(testHilo);
}
transaction.Commit();
}
Такой код вставит все 60 записей.
Полезненько, добавил в nHibernate Tricks =)
ReplyDelete