Unit OF Work
工作单元
eXpress Persistent Objects can now perform semi-automatic change tracking using the Unit of Work principle. A Unit of Work maintains a list of persistent objects that are affected by a transaction. It keeps track of every change to every persistent object during a transaction that can affect a data store. With a single call to the UnitOfWork.CommitChanges method all the changes made to the persistent objects are automatically saved to a data store. When working with common sessions you need to save each persistent object individually.
A Unit of Work is represented by a UnitOfWork class. It inherits the base functionality from the Session class and provides the UnitOfWork.CommitChanges method that is used to save the changed persistent objects to a data store. The only requirement for this is that the property setters call the XPBaseObject.OnChanged method.
持久对象表示现在可以执行半自动更改跟踪使用单位的工作原理。一个工作单元保持持久对象列表,受一个事务的影响。它使每一个变化的轨迹持久对象的每一个事务中可能影响数据存储。使用单个调用UnitOfWork.CommitChanges方法的所有的变化作出的持久对象会自动保存到数据库。当工作需要保存每个持久对象单独的共同会话。
一个工作单元由一个UnitOfWork类。它继承了从阶级基础会话功能,并提供了UnitOfWork.CommitChanges方法用于保存更改的持久对象的数据存储。此唯一的要求是,这些属性制定者调用XPBaseObject.OnChanged方法。
Declaring a Persistent Object(定义一个持久对象)
class UOWPerson : XPObject {
public UOWPerson(Session session) : base(session) { }
public UOWPerson(Session session, string name) : base(session) {
this.name = name;
}
private string name;
public string Name {
get { return name; }
set {
// The old value of the Name property.
string oldValue = Name;
if(oldValue == value)
return;
name = value;
// Keep track of every change made to the Name property.
OnChanged("Name", oldValue, value);
}
}
}
Note:
The Name property's set accessor calls the XPBaseObject.OnChanged method to keep track of the changes made to this property. Once the Unit of Work's UnitOfWork.CommitChanges method is called, the changes will be automatically saved to a data store. You should always implement properties this way if you want changes to be recognized automatically in Units of Work.
注意:
Name属性的set访问器调用XPBaseObject.OnChanged方法保持在作出此属性的更改。一旦工作的方法被称为UnitOfWork.CommitChanges,更改将自动保存到数据库。您应该实现这样的属性,如果你想改变承认工作单位自动。
Using Units of Work in XPO(在XPO中使用工作单元)
The following sample creates a new instance of the UnitOfWork class (uow object) with default settings. In this case there's no specific rollback code, the changes are only committed to the database if the UnitOfWork.CommitChanges method is executed. The UnitOfWork class derives from Session, and so all objects that are being handled within a unit must be fetched via that unit or associated with it by means of the session constructors in the XPO base classes.
下面的示例创建一个UnitOfWork类(uow object)的新实例。在这种情况下,有没有具体的回滚代码,这些变化只是承诺,如果UnitOfWork.CommitChanges方法执行数据库。类派生的UnitOfWork从会话,因此所有目前在一个单位处理的对象必须是通过提取单位或与之相关联的在XPO基类构造方法的会议。
using(UnitOfWork uow = new UnitOfWork()) {
// Create, update or delete objects
uow.CommitChanges();
}
Then we create three persistent objects of the UOWPerson type that has been declared above. If the Session has been used, we had to save each persistent object individually by calling its XPBaseObject.Save method. While using the Unit of Work only one UnitOfWork.CommitChanges method call is needed to save all the changes made.
然后,我们创建三种类型的UOWPerson已宣布上述持久对象。如果会话已被使用,我们不得不节省调用它的方法XPBaseObject.Save每个持久对象个别。当使用工作单元只有一个UnitOfWork.CommitChanges方法调用是需要保存所有更改。
using(UnitOfWork uow = new UnitOfWork()) {
UOWPerson p = new UOWPerson(uow, "Mike");
// p.Save(); when working with a Session
p = new UOWPerson(uow, "John");
// p.Save(); when working with a Session
p = new UOWPerson(uow);
p.Name = "Bob";
// p.Save(); when working with a Session
// Save all the changes made.
uow.CommitChanges();
}
Internally, the UnitOfWork class uses a single transaction that is started automatically, committed in the UnitOfWork.CommitChanges method and rolled back when the unit is being disposed.
在内部,UnitOfWork类使用一个单一的交易自动启动,在UnitOfWork.CommitChanges方法承诺和回滚的单位处置。
Nested Units of Work(工作单元嵌套)
A Nested Unit of Work is a new Unit of Work begun from within the scope of a Session or another Unit of Work. Changes that are being made within these nested units will be merged back into the outer session if the nested unit is committed, or discarded otherwise. As the nested unit works with clones of the data, changes that are being done within it do not immediately effect the outer session.
Nested Units of Work provide the following features:
· Enable an application to isolate errors in certain operations.
· Allow an application to treat several related operations as a single atomic operation.
· The depth of the nesting is limited only by memory.
嵌套的工作单位是一个新的工作单位内的会议或其它工作单位的范围开始。正在嵌套在这些单位进行的更改将合并回外部会议如果嵌套单位承诺,或丢弃的除外。由于与数据,这已被纳入它不会立即生效的外部会议所做的改变克隆嵌套单位工程。嵌套工作单位提供下列功能:使应用程序隔离在某些操作上的错误。允许应用程序处理几个相关的业务作为一个单一的原子操作。嵌套深度只受内存限制。
Nested Units of Work are represented by a NestedUnitOfWork class. A Session or Unit of Work that starts the nested Unit of Work is called the parent of the nested Unit of Work.
To create a new nested Unit of Work, call its parent's Session.BeginNestedUnitOfWork method. XPO will automatically create a new instance of the NestedUnitOfWork class with the specified parent.
To commit or discard the changes made within the nested Unit of Work since it was started, use the UnitOfWork.CommitChanges and Session.RollbackTransaction methods, respectively. Committing a nested Unit of Work has no effect on the state of its parent. The parent (a UnitOfWork instance) is still uncommitted until its UnitOfWork.CommitChanges method is called.
嵌套工作单位是由一NestedUnitOfWork类。某届或工作单位的启动工作嵌套组被称为嵌套的工作单位的父母。要创建新的工作嵌套组,请其母公司的Session.BeginNestedUnitOfWork方法。 XPO会自动创建一个具有指定的母公司NestedUnitOfWork类的新实例。提交或丢弃在工作嵌套组作出的变化,因为它开始使用UnitOfWork.CommitChanges和Session.RollbackTransaction方法分别。犯嵌套组的工作并没有就其母公司状态的影响。父(1 UnitOfWork实例)仍然未提交直至UnitOfWork.CommitChanges方法被调用。
using(UnitOfWork parent = new UnitOfWork()) {
...
using(NestedUnitOfWork nestedUOW = parent.BeginNestedUnitOfWork()) {
...
nestedUOW.CommitChanges();
}
....
parent.CommitChanges();
}
While the nested Unit of Work is active, it is not recommended to perform any operations with its parent. In this instance, you should first commit or roll back the nested Unit of Work and only then its parent. Nested Units of Work cannot operate concurrently.
虽然工作嵌套股活跃,不建议执行与母公司的任何行动。在这种情况下,应首先提交或回滚的工作,只有在其父母嵌套股。嵌套的工作单位不能同时运作。
Using Transactions
A transaction is a sequential group of manipulation operations, which is performed as if it were one single work unit. In other words, a transaction will never be complete unless each individual operation within the group is successful. If any operation within the transaction fails, the entire transaction will fail
Transactions have the following four standard properties (ACID properties):
一个事务是一个处理操作,这是完成串行组就好像它是一个单一的工作单位。换言之,交易将永远不会完成,除非每一个集团内的个体经营是成功的。如果交易中的任何操作失败,整个交易将失败的交易有以下四点(ACID属性)标准属性:
Transactions have the following four standard properties (ACID properties):
· Atomicity: ensures that all operations within the work unit are completed successfully; otherwise, previous operations are rolled back to their former state.
· Consistency: requires that data bound by a transaction be semantically preserved.
· Isolation: the result of individual transaction must be transparent to any other open transaction until that transaction commits successfully.
· Durability: ensures that the result or effect of a committed transaction persists in case of a system failure.
事务具有以下四个标准属性(ACID属性):
原子性:确保工作单位内的所有操作都成功完成,否则,以前的操作回滚到其以前的状态。
一致性:要求交易数据在语义约束保留。
隔离:对个人交易的结果必须是透明的,任何其它打开的事务,直到该事务提交成功。
持久性:确保结果或提交事务的影响仍然存在在系统发生故障时。
To begin a transaction, call the session's Session.BeginTransaction method. If a Unit of Work is used, a transaction is started automatically
要开始一个事务,调用会话的Session.BeginTransaction方法。如果一个工作组使用,交易自动启动
COMMIT and ROLLBACK
When a successful transaction is completed, the COMMIT command should be issued so that the changes to all involved persistent objects will take effect. To do this, call the Session.CommitTransaction method. If a failure occurs, a ROLLBACK command should be issued to return every persistent object in the transaction to its previous state. In this instance, the Session.RollbackTransaction method must be used. It completes the transaction discarding all the changes made since the transaction was started.
Typically these methods are used in code like this:
当一个成功的事务完成后,应在COMMIT命令发出,让所有参与的持久对象的更改将生效。为此,调用Session.CommitTransaction方法。如果发生故障,一个ROLLBACK命令应发出返回交易每个持久对象到以前的状态。在这种情况下,Session.RollbackTransaction方法必须使用。在完成交易抛弃了所有的变化,因为交易开始。通常这些在代码中使用这样的方法:
using (Session session = new Session()) {
session.BeginTransaction();
try {
// Create, update or delete objects
session.CommitTransaction();
}
catch {
session.RollbackTransaction();
throw;
}
}
Since transactions on the XPO layer don't correspond to transactions on the database layer, it is possible to have long-running transactions in XPO without promoting concurrency issues in multi-user use cases. Only when a transaction is committed, a short database transaction is started to apply the changes.
To see if a transaction is in progress use the Session.InTransaction property.
由于在XPO层交易不符合在数据库层的交易,很可能有长远运行XPO没有问题,促进并发多用户使用的情况下交易。只有当一事务提交时,短数据库事务的开始应用更改。要查看交易正在进行使用Session.InTransaction财产。
Isolation(隔离)
When a transaction is running and there are uncommitted changes in it - remember that transactions are also the basis of Units of Work.Connecting to a Data Store and they don't correspond to database transactions - a newly constructed XPCollection will not normally be able to "see" the changes that have been made in the current transaction. This is because the collection fetches its content from the database, but the changes have not yet been written there. This is the default behaviour, but we have introduced a flag called PersistentCriteriaEvaluationBehavior that allows you to see a merged state of the data, where changes from the current running transaction are already included.
See the code below. The default collection - which uses the enum value PersistentCriteriaEvaluationBehavior.BeforeTransaction internally - does not see the newly created object, while the collection with the specified behavior PersistentCriteriaEvaluationBehavior.InTransaction finds both the old and the new object.
当一个事务正在运行,并且有未提交也变化-记住,事务也是对Work.Connecting的数据存储单元的基础上,他们不符合数据库事务-新建成的XPCollection通常不会能“看到”已在当前事务中所做的更改。这是因为集从数据库中提取的内容,但这种变化还没有被写入那里。这是默认的行为,但我们推出的一种名为PersistentCriteriaEvaluationBehavior一个标志,让你在哪里看到从目前运行的事务变化已经包含的数据,合并后的状态。看下面的代码。默认集合-它使用枚举值PersistentCriteriaEvaluationBehavior.BeforeTransaction国内-没有看到新创建的对象,而与指定的行为PersistentCriteriaEvaluationBehavior.InTransaction收集发现新旧两种新的对象。
// Clear the database and create one object.
using (Session session = new Session( )) {
session.ClearDatabase( );
new Person(session, "Willy Watt").Save();
}
using (UnitOfWork unitOfWork = new UnitOfWork( )) {
// Create a second object.
new Person(unitOfWork, "Billy Bott").Save( );
XPCollection<Person> people = new XPCollection<Person>(unitOfWork);
// This collection doesn't see the new object.
Debug.Assert(people.Count == 1, "Wrong count");
people = new XPCollection<Person>(PersistentCriteriaEvaluationBehavior.InTransaction,
unitOfWork, null);
// This collection sees both objects.
Debug.Assert(people.Count == 2, "Wrong count");
}