(一)对象的标识以及Database到Object的映射
If two instances of Employee have the same identifier value, they represent the same row in the database。
这里指的是如果两个对象具有同样的ID,那么他们代表数据库中的同一行。也就是说这是Database到Object映射的一个维度,是通过ROWID来完成对象级别的映射的。
Q:那么因此对Object的Compare来说,是否需要需要重写Equals方法?NHibernate会默认重写Object的Equals方法么或者提供对象的Compare方法?
A: 仍然需要。在Test的代码中,采用同一个ID从Session中获取Object的时候,此时Make Object ID发现获取的Object是一样的,这是由于NH对Object的Cache导致的,所以等采用同一个ID从不同的Session中获取Object的时候发现此时是不一样的。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
| [TestCase] public void TestObjectThatGetsFromSessionAreEqual() { const string strName = "Test"; Employee employee = new Employee(); employee.Name = strName; Employee employeeCompare = new Employee(); employeeCompare.Name = "employeeComare.Name"; Assert.AreNotEqual(employeeCompare, employee); using (ISession session = OpenSession()) { using (ITransaction tx = session.BeginTransaction()) { session.Save(employee); session.Save(employeeCompare); tx.Commit(); } } int id = employee.ID; using (ISession session = OpenSession()) { employee = session.Get<Employee>(id); var employeeCompareFromSameSession = session.Get<Employee>(id); Assert.AreEqual(employee, employeeCompareFromSameSession); Assert.AreSame(employee, employeeCompareFromSameSession); } using (ISession session = OpenSession()) { employeeCompare = session.Get<Employee>(id); Assert.AreNotEqual(employee, employeeCompare, "They are not equal"); Assert.AreNotSame(employee, employeeCompare); } }
|
Q: 如果使用同一ID去获取对象,这两个对象是Reference Equal么?如果不是,NH就可能每次都去数据库取一次了,如果是,比如存在缓存。
A:示例如上所示,由于Session的cache 的作用,这两个是Reference Equal的。
Q: 改变一个Object的ID会产生什么影响?
A: 此时会抛出来异常。failed: NHibernate.HibernateException : identifier of an instance of HelloNH.Employee was altered from 23 to 2222
另外如果在代码中设置了Object的ID的话,NH仍然会按照自己的思路修改这个ObjectID,只要Object纳入了Session的管理中,那么异常就会抛出来。其实看一下调用的堆栈卡可以猜测,NH通过一系列的事件来管理起来所有的Object了,任何对Object的修改都会触发事件响应。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
| [TestCase] public void TestChangeObjectID() { Assert.Catch<HibernateException>( delegate{ Employee e = new Employee() { Name = "Employeee name" }; e.ID = 1111; using (ISession sesion = OpenSession()) { using (ITransaction tx = sesion.BeginTransaction()) { sesion.Save(e); //此?时骸?已?经-抛×出?来ぁ?异馬?常£了? e.ID = 2222; tx.Commit(); e.ID = 5555; } } }); }
|
作者说"Instances of the Employee class may be managed(made persistent) by NHibernate", 呵呵,用了个May Be。
Q: 如果传过来的Object为NULL, NHibernate会怎么出来?报错么?我觉得会报错。处理方式有两种么:跳过,或者报错。报错能让我知道结果。
A:报错. attempt to create saveOrUpdate event with null entity。