您的位置:首页 > 其它

NHibernate官方文档中文版--只读实体类型(Read-only entities)

2016-11-02 14:49 489 查看
重点
NHIbernate处理只读对象的方式可能和你在别处看到的不同。不正确的使用方式可能造成不可预料的结果。

当一个实体是只读的时候:

NHIbernate不会对实体的简单属性和单向关联数据检查数据是否是脏数据

NHibernate不会对实体的简单属性和单向关联数据进行更新操作

NHibernate不会更新只读对象的版本信息,尽管实体的简单属性和单向关联数据发生了改变

在某些情况下,NHibernate对待一些只读实体类型和费只读类型是一样的:

Nhibernate级联操作定义在实体mapping中的关联对象

Nhibernate在实体包含的集合被修改之后会更新它的版本信息

只读实体被删除

尽管一个实体不是只读的,它的管理集合对象如果包含只读实体,它还是会受到影响。

NHibernate会对只读实体进行一些优化:

它节约了执行时间,因为不需要对实体的简单属性和单向关联数据进行脏数据检查

它通过删除数据库快照来节约内存

如何使持久化对象只读

只有持久化对象才能成为只读类型。瞬时态和游离态的对象在转化成只读状态之前必须成为持久化状态。

NHibernate提供了下面的几种方法让持久化对象成为只读类型:

你可以将实体类型映射成不变类型,当一个不变类变成持久化状态的时候,NHibernate会自动将它变成只读类型。

你可以改变默认值,因此实体在加载到这个session中的时候会自动转化成只读类型。

你可以让一个HQL查询或者条件查询只读,因此当这个HQL或者条件查询执行,或者遍历的时候,都会自动变成只读类型。

你可以让一个session中的持久化实体只读。

不可变类型实体

当一个不变类实体实例转化成持久化状态的时候,NHibernate会自动让它变成只读类型。

一个不可变类可以像一个可变类一样新增和删除。

NHibernate对待一个不可变类型的持久化实体和不可变实体的只读持久化类型是一样的。唯一的不同是NHibernate不允许不可变类实体改变,即使它不是只读类型。(吐槽:真搞不懂,整个文档一直颠来倒去地重复说这句话有什么意义)

将持久化对象加载成只读类型的

注意

不可变类会被自动加载成只读类型。

要改变NHibernate加载不可变类型的时候自动将它转化成只读的默认行为,调用:

Session.DefaultReadOnly = true;


想要改变回去,调用

Session.DefaultReadOnly = false;


你可以通过使用这属性来决定当前的设定

Session.DefaultReadOnly;


如果Session.DefaultReadOnly 属性返回true,被下面方法加载的实体会自动变成只读类型:

If Session.DefaultReadOnly property returns true, entities loaded by the following are automatically made read-only:

Session.Load() 和 Session.Load<T>

Session.Get() 吧、和 Session.Get<T>

Session.Merge()

Changing this default has no effect on:改变这个默认值不会对下面实体产生影响:

persistent entities already in the session when the default was changed默认配置改变的时候已经在session中的持久化实体

persistent entities that are refreshed via Session.Refresh(); a refreshed persistent entity will only be read-only if it as read-only before refreshing通过Session.Refresh()刷新的持久化实体;一个已经被刷新的持久化实体将只会是只读的,如果在它刷新之前是只读的

persistent entities added by the application via Session.Persist(), Session.Save(), and Session.Update()Session.SaveOrUpdate()应用程序通过Session.Persist(), Session.Save(), Session.Update() 或者 Session.SaveOrUpdate()添加的持久化实体。

通过HQL/条件查询来加载只读实体(不推荐使用HQL和criteria)

Note

Entities of immutable classes are automatically loaded as read-only.

If Session.DefaultReadOnly returns false (the default) when an HQL query or criteria executes, then entities and proxies of mutable classes loaded by the query will not be read-only.

You can override this behavior so that entities and proxies loaded by an HQL query or criteria are automatically made read-only.

For an HQL query, call:

Query.SetReadOnly(true);


Query.SetReadOnly(true) must be called before Query.List(), Query.UniqueResult(), or Query.Iterate()

For an HQL criteria, call:

Criteria.SetReadOnly(true);


Criteria.SetReadOnly(true) must be called before Criteria.List(), or Criteria.UniqueResult()

Entities and proxies that exist in the session before being returned by an HQL query or criteria are not affected.

Uninitialized persistent collections returned by the query are not affected. Later, when the collection is initialized, entities loaded into the session will be read-only if Session.DefaultReadOnly returns true.

Using Query.SetReadOnly(true) or Criteria.SetReadOnly(true) works well when a single HQL query or criteria loads all the entities and intializes all the proxies and collections that the application needs to be read-only.

When it is not possible to load and initialize all necessary entities in a single query or criteria, you can temporarily change the session default to load entities as read-only before the query is executed. Then you can explicitly initialize proxies and collections before restoring the session default.

ISession session = factory.OpenSession();
ITransaction tx = session.BeginTransaction();

session.DefaultReadOnly = true;
Contract contract = session.CreateQuery("from Contract where CustomerName = 'Sherman'").UniqueResult<Contract>();
NHibernate.Initialize(contract.Plan);
NHibernate.Initialize(contract.Variations);
NHibernate.Initialize(contract.Notes);
session.DefaultReadOnly = false;
...
tx.Commit();
session.Close();


If Session.DefaultReadOnly returns true, then you can use Query.SetReadOnly(false) and Criteria.SetReadOnly(false) to override this session setting and load entities that are not read-only.

让一个实体变成只读类型

想要让一个持久化实体或者代理只读,调用

To make a persistent entity or proxy read-only, call:

Session.SetReadOnly(entityOrProxy, true)


要改变一个不可变类型的只读实体或代理来让它不是只读的,调用

To change a read-only entity or proxy of a mutable class so it is no longer read-only, call:

Session.SetReadOnly(entityOrProxy, false)


重要

当一个只读实体或者代理改变成不是只读的时候,NHibernate会假设只读实体的状态和它的字段是一致的。如果不是这样的话,任何在之前或者在改变状态的时候还没有flush的改变,都会被忽略。

要抛弃未flush的改变,让持久化实体的状态和字段一致,调用:

When a read-only entity or proxy is changed so it is no longer read-only, NHibernate assumes that the current state of the read-only entity is consistent with its database representation. If this is not true, then any non-flushed changes made before or while the entity was read-only, will be ignored.

To throw away non-flushed changes and make the persistent entity consistent with its database representation, call:

Session.Refresh(entity);


想要flush在之前或者在改变状态的时候的改变,然后和数据库一致:

To flush changes made before or while the entity was read-only and make the database representation consistent with the current state of the persistent entity:

// evict the read-only entity so it is detached
session.Evict(entity);

// make the detached entity (with the non-flushed changes) persistent
session.Update(entity);

// now entity is no longer read-only and its changes can be flushed
s.Flush();


Read-only affect on property type只读类型对属性类型的影响

下面的表格总结了使一个实体变成只读状态之后不同属性类型会受到怎样的影响:

The following table summarizes how different property types are affected by making an entity read-only.

Table Affect of read-only entity on property types

属性/关联对象类型flush之后是否会改变
简单属性

单向的一对一

单向的多对一


单向的一对多

单向的多对多


双向的一对一仅仅在实体不是只读的时候会改变
双向的一对多/多对一

集合反向

集合非反向

仅仅添加/删除非只读类型实体的时候会改变
双向的多对多
*当实体包含只读属性或者关联对象的时候是不一样的。

简单属性

当一个持久化实体是只读的时候,Nhibernate不会对简单属性进行脏检查(dirty-check )。

NHibernate不会同步简单属性的状态到数据库中。如果你使用了自动版本控制,Nhibernate不会更新版本信息。

When a persistent object is read-only, NHibernate does not dirty-check simple properties.

NHibernate will not synchronize simple property state changes to the database. If you have automatic versioning, NHibernate will not increment the version if any simple properties change.

ISession session = factory.OpenSession();
ITransaction tx = session.BeginTransaction();

// get a contract and make it read-only
Contract contract = session.Get<Contract>(contractId);
session.SetReadOnly(contract, true);

// contract.CustomerName is "Sherman"
contract.CustomerName = "Yogi";
tx.Commit();

tx = session.BeginTransaction();

contract = session.Get<Contract>(contractId);
// contract.CustomerName is still "Sherman"
...
tx.Commit();
session.Close();


Unidirectional associations

Unidirectional one-to-one and many-to-one

当包含只读实体的时候,Nhibernate处理单向的一对一和多对一关联是相同的。

当讨论单方向的一对一和多对一关联的时候,我们会使用我们使用无方向的单向这个名词。

当包含只读实体的时候,Nhibernate不会对单向的关联进行脏检查。

如果你把只读实体的关联从单向关联变为null,或者变成其他实体,flush之后改变不会提交到数据库。

注意

如果一个不可变实体引用一个单向实体,它必须因为实体会自动被设置成只读,这些引用都不会被更新。

如果使用了自动版本控制,Nhibernate不会把单向关联的版本信息更新。

在下面的例子中,Contract有一个单向的多对一的Plan关联。Contract会级联保存和更新它的关联实体。

下面的例子战士了改变一个只读的多对一关系到null并不会影响实体数据库的信息。

NHibernate treats unidirectional one-to-one and many-to-one associations in the same way when the owning entity is read-only.

We use the term unidirectional single-ended association when referring to functionality that is common to unidirectional one-to-one and many-to-one associations.

NHibernate does not dirty-check unidirectional single-ended associations when the owning entity is read-only.

If you change a read-only entity's reference to a unidirectional single-ended association to null, or to refer to a different entity, that change will not be flushed to the database.

Note
If an entity is of an immutable class, then its references to unidirectional single-ended associations must be assigned when that entity is first created. Because the entity is automatically made read-only, these references can not be updated.

If automatic versioning is used, NHibernate will not increment the version due to local changes to unidirectional single-ended associations.

In the following examples, Contract has a unidirectional many-to-one association with Plan. Contract cascades save and update operations to the association.

The following shows that changing a read-only entity's many-to-one association reference to null has no effect on the entity's database representation.

// get a contract with an existing plan;
// make the contract read-only and set its plan to null
tx = session.BeginTransaction();
Contract contract = session.Get<Contract>(contractId);
session.SetReadOnly(contract, true);
contract.Plan = null;
tx.Commit();

// get the same contract
tx = session.BeginTransaction();
Contract contract = session.Get<Contract>(contractId);

// contract.Plan still refers to the original plan;

tx.Commit();
session.Close();


The following shows that, even though an update to a read-only entity's many-to-one association has no affect on the entity's database representation, flush still cascades the save-update operation to the locally changed association.

下面的例子展示了,尽管一个对只读实体多对一关联的更新不会影响实体的数据库信息,flush操作仍然会级联执行本地关联的save-update操作。

// get a contract with an existing plan;
// make the contract read-only and change to a new plan
tx = session.BeginTransaction();
Contract contract = session.Get<Contract>(contractId);
session.SetReadOnly(contract, true);
Plan newPlan = new Plan("new plan");
contract.Plan = newPlan;
tx.Commit();

// get the same contract
tx = session.BeginTransaction();
contract = session.Get<Contract>(contractId);
newPlan = session.Get<Plan>(newPlan.Id);

// contract.Plan still refers to the original plan;
// newPlan is non-null because it was persisted when
// the previous transaction was committed;

tx.Commit();
session.Close();


Unidirectional one-to-many and many-to-many

NHibernate treats unidirectional one-to-many and many-to-many associations owned by a read-only entity the same as when owned by an entity that is not read-only.

NHibernate dirty-checks unidirectional one-to-many and many-to-many associations;

The collection can contain entities that are read-only, as well as entities that are not read-only.

Entities can be added and removed from the collection; changes are flushed to the database.

If automatic versioning is used, NHibernate will update the version due to changes in the collection if they dirty the owning entity.

当包含只读实体的时候,Nhibernate处理单向的一对多和多对多关联是相同的。

NHibernate会对单向的一对多和多对对关系进行脏检查。

集合可以包含只读实体,它们的改变会被flush操作提交到数据库。

如果使用了自动版本机制,Nhibernate会在修改提交后更新版本信息。

Bidirectional associations

Bidirectional one-to-one

如果一个只读实体包含了双向的一对一关联:

NHibernate不会对关系进行脏检查

将关联引用到null或者其他的实体类型的修改操作不会被flush到数据库中

如果使用了自动版本功能,NHibernate不会因为本地数据的改变而更新版本信息

注意

如果一个实体是不可变类型,并且它包含双向的一对一关联,当这个实体第一次被创建的时候,它的引用必须被assigned。因为这个实体会自动变成只读的,而这些引用不能被更新。

当所有者不是只读的时候,NHibernate处理只读实体关联和非只读实体关联是一样的。

If a read-only entity owns a bidirectional one-to-one association:

NHibernate does not dirty-check the association.

updates that change the association reference to null or to refer to a different entity will not be flushed to the database.

If automatic versioning is used, NHibernate will not increment the version due to local changes to the association.

Note
If an entity is of an immutable class, and it owns a bidirectional one-to-one association, then its reference must be assigned when that entity is first created. Because the entity is automatically made read-only, these references cannot be updated.

When the owner is not read-only, NHibernate treats an association with a read-only entity the same as when the association is with an entity that is not read-only.

Bidirectional one-to-many/many-to-one

一个只读实体不会影响双向多对一/一对多关联,如果:

只读实体在一对多的一端并且使用反转集合

只读实体在一对多的一端并且不使用反转集合

一对多一段使用非反转集合并且包含只读实体

当一对多端使用一个反转集合

一个只读实体只能在集合生成的时候添加进去

一个只读实体只能怪通过显示的孤儿删除方式来移除出集合

A read-only entity has no impact on a bidirectional one-to-many/many-to-one association if:

the read-only entity is on the one-to-many side using an inverse collection;

the read-only entity is on the one-to-many side using a non-inverse collection;

the one-to-many side uses a non-inverse collection that contains the read-only entity

When the one-to-many side uses an inverse collection:

a read-only entity can only be added to the collection when it is created;

a read-only entity can only be removed from the collection by an orphan delete or by explicitly deleting the entity.

Bidirectional many-to-many

双向多对多

当包含只读实体的时候,Nhibernate处理双向的多对多关联是相同的。

NHibernate会对双向的多对多和多对对关系进行脏检查。

集合无论在哪端都可以包含只读实体和费只读实体。

实体可以从任意端添加或者删除,这些改变都会通过flush操作提交到数据库。

如果使用了自动版本机制,对于来自任意一端的修改,Nhibernate会在修改提交后更新版本信息。

NHibernate treats bidirectional many-to-many associations owned by a read-only entity the same as when owned by an entity that is not read-only.

NHibernate dirty-checks bidirectional many-to-many associations.

The collection on either side of the association can contain entities that are read-only, as well as entities that are not read-only.

Entities are added and removed from both sides of the collection; changes are flushed to the database.

If automatic versioning is used, NHibernate will update the version due to changes in both sides of the collection if they dirty the entity owning the respective collections.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: