NHibernate – 加载/获取
NHibernate – 加载/获取
在本章中,我们将介绍 Load 和 Get 功能的工作原理以及如何使用它们。这是ISession提供的两个非常相似的 API,用于通过主键加载对象。
-
Get – 它将返回对象或空值。
-
Load – 它将返回对象或抛出ObjectNotFoundException。
现在,为什么我们有这两个不同的 API?
加载
-
这是因为 Load 可以更有效地优化数据库往返。
-
Load 实际上返回一个代理对象,并且在您发出 Load 调用时不需要访问数据库。
-
当您访问该代理时,该对象恰好不在数据库中,此时它可能会抛出 ObjectNotFoundException。
得到
-
相反,由于 CLR 或公共语言运行时和 NHibernate的限制,使用 Get必须立即转到数据库,检查对象是否在那里,如果不存在则返回 null。
-
它没有延迟提取的对象选项,因为它无法返回代理对象并且在用户实际访问它时将该代理对象交换为空值。
让我们看一个简单的例子,在这个例子中你会看到这些是如何实际使用的,以及 Get 和 Load 之间的区别。我们将继续使用相同的域类Customer和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,第一个是一个好的 ID,它是我们知道在数据库中的客户 ID。而数据库中不存在第二个 ID。这两个 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