NHibernate - Загрузить / получить
В этой главе мы расскажем, как работают функции загрузки и получения и как мы можем их использовать. Это два очень похожих API, предоставляемыхISession для загрузки объекта по первичному ключу.
Get - он вернет объект или нуль.
Load - он вернет объект или бросит ObjectNotFoundException.
Итак, почему у нас есть эти два разных API?
Загрузить
Это потому, что Load может намного более эффективно оптимизировать круговые обходы базы данных.
Load фактически возвращает прокси-объект, и ему не нужно обращаться к базе данных сразу после вызова этого Load.
Когда вы обращаетесь к этому прокси-серверу, объекта не бывает в базе данных, в этот момент он может вызвать исключение ObjectNotFoundException.
Получить
И наоборот, с Get из-за ограничений CLR или Common Language Runtime и NHibernate должен немедленно перейти в базу данных, проверить, есть ли там объекты, и вернуть null, если его нет.
У него нет возможности объекта отложить эту выборку, этот обратный путь к базе данных на более позднее время, потому что он не может вернуть прокси-объект и заменил этот прокси-объект на ноль, когда пользователь фактически обращается к нему.
Давайте рассмотрим простой пример, в котором вы увидите, как они на самом деле используются, и разницу между Get и Load. Мы продолжим с теми же предметными классамиCustomers и Orders и аналогично те же файлы сопоставления из предыдущей главы.
В этом примере мы сначала будем использовать Get, как показано в следующей программе.
using System;
using System.Data;
using System.Linq;
using System.Reflection;
using HibernatingRhinos.Profiler.Appender.NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Linq;
namespace NHibernateDemo {
internal class Program {
private static void Main() {
var cfg = ConfigureNHibernate();
var sessionFactory = cfg.BuildSessionFactory();
using(var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction()) {
var id1 = Guid.Parse("4e97c816-6bce-11e1-b095-6cf049ee52be");
var id2 = Guid.Parse("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE");
var customer1 = session.Get<Customer>(id1);
Console.WriteLine("Customer1 data");
Console.WriteLine(customer1);
var customer2 = session.Get<Customer>(id2);
Console.WriteLine("Customer2 data");
Console.WriteLine(customer2);
tx.Commit();
}
Console.WriteLine("Press <ENTER> to exit...");
Console.ReadLine();
}
private static Configuration ConfigureNHibernate() {
NHibernateProfiler.Initialize();
var cfg = new Configuration();
cfg.DataBaseIntegration(x => {
x.ConnectionStringName = "default";
x.Driver<SqlClientDriver>();
x.Dialect<MsSql2008Dialect>();
x.IsolationLevel = IsolationLevel.RepeatableRead;
x.Timeout = 10;
x.BatchSize = 10;
});
cfg.SessionFactory().GenerateStatistics();
cfg.AddAssembly(Assembly.GetExecutingAssembly());
return cfg;
}
}
}
Как видите, у нас есть два GuidИдентификаторы, первый - хороший идентификатор, это идентификатор клиента, который, как мы знаем, есть в базе данных. Пока второго ID нет в базе. Оба этих идентификатора передаются как параметр вGet() метод, а затем результат выводится на консоль.
Когда приведенный выше код скомпилирован и выполнен, вы увидите следующий результат.
Customer1 data
Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
Points: 74
HasGoldStatus: True
MemberSince: 4/4/2009 12:00:00 AM (Utc)
CreditRating: Neutral
AverageRating: 0
Orders:
Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
Customer2 data
Press <ENTER> to exit...
Как вы можете видеть, данные Customer1 печатаются, но данные Customer2 пусты, это потому, что запись Customer2 недоступна в базе данных.
Когда вы снова запустите приложение, мы можем вставить точку останова перед оператором фиксации, а затем посмотрим на обоих клиентов в окне Watch.
Как видите, данные Customer1 доступны, в то время как Customer2 имеет значение null, а тип - NHibernateDemo.Customer для обоих.
Теперь давайте воспользуемся методом Load вместо Get в том же примере, который показан в следующем коде.
using System;
using System.Data;
using System.Linq;
using System.Reflection;
using HibernatingRhinos.Profiler.Appender.NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Linq;
namespace NHibernateDemo {
internal class Program {
private static void Main() {
var cfg = ConfigureNHibernate();
var sessionFactory = cfg.BuildSessionFactory();
using(var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction()) {
var id1 = Guid.Parse("4e97c816-6bce-11e1-b095-6cf049ee52be");
var id2 = Guid.Parse("AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE");
var customer1 = session.Load<Customer>(id1);
Console.WriteLine("Customer1 data");
Console.WriteLine(customer1);
var customer2 = session.Load<Customer>(id2);
Console.WriteLine("Customer2 data");
Console.WriteLine(customer2);
tx.Commit();
}
Console.WriteLine("Press <ENTER> to exit...");
Console.ReadLine();
}
private static Configuration ConfigureNHibernate() {
NHibernateProfiler.Initialize();
var cfg = new Configuration();
cfg.DataBaseIntegration(x => {
x.ConnectionStringName = "default";
x.Driver<SqlClientDriver>();
x.Dialect<MsSql2008Dialect>();
x.IsolationLevel = IsolationLevel.RepeatableRead;
x.Timeout = 10;
x.BatchSize = 10;
});
cfg.SessionFactory().GenerateStatistics();
cfg.AddAssembly(Assembly.GetExecutingAssembly());
return cfg;
}
}
}
Теперь давайте запустим этот пример, и вы увидите, что возникает следующее исключение, как показано на снимке экрана.
Теперь, если вы посмотрите в окно Watch, вы увидите, что типом является прокси клиента для обоих объектов. Вы также видите те же данные для Customer1 в окне консоли.
Customer1 data
Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
Points: 74
HasGoldStatus: True
MemberSince: 4/4/2009 12:00:00 AM (Utc)
CreditRating: Neutral
AverageRating: 0
Orders:
Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
Customer2 data