通过第一部分的介绍,我们对这个Audit Logging解决方案的原理有了较为全面的了解,接下来我们将通过一个简单的Sample来进一步介绍如何在一个具体的应用中如何实现这样一个Audit Logging。
我们沿用在Part I提出的Order management 场景,为了简单起见,我们通过一个Console application来模拟。在这个Application中,你将会看到如何以一种离线的模式操作数据库,如何Log这些操作。
我们首先来介绍Sample程序的结构(如下图)。整个Solution 一共包括两个Project,一个Console application,另一个是用以管理和定义Stored Procedure和Trigger的Database project。我们现在就来一步步实现这样一个Order management的简单的应用。Source Code从Artech.WCFService.zip下载。
![](https://i-blog.csdnimg.cn/blog_migrate/2fec9f95cc2943de97a72085e16fe3bd.jpeg)
一.定义一个轻型的Data access 的Helper class。
在Part I中我提到过这样一个Helper class,虽然这不是本篇所要介绍的重点,但是为了让读者能够较为全面地了解整个处理流程,在这里我对她作一个简单的介绍。
我在前一阵子,写过一篇叫做[原创]我的ORM: 开发自己的Data Access Application Block 的文章,在这片文章中我开发了一个自定义的DAB。我这个Data access helper便是采用里面提出的思想,实现了其中一小部分功能:Data retrieval, Update Dataset和Transaction。力求简洁,我剔出掉其中可配置的data mapping部分采用hard coding的方式实现Dataset和Stored procedure的Mapping。
通过这个Helper class,你可以调用UpdateData方法把对一个Table作的修改向数据库提交。这个方法的思路是这样的:我们对该Table的增加、修改和删除均定义了一个Stored procedure,我们假设Table name和Stored procedure name之间,Stored procedure的每个Parameter 的名称和Table中的Field name和DataRowVersion存在一个Mapping。比如T_ORDER对应的增加、修改和删除stored procedure分别为sp_order_i,sp_order_u和sp_order_d;stored procedure的参数@p_order_id对应的Source column为ORDER_ID, SourceVersion为DataRowVersion.Current,而参数@o_order_id对应的SourceVersion为DataRowVersion.Original。有了这样一个Mapping为前提,相信大家对Helper class的实现原理应该想象得到。当然要使我们的Stored procedure满足这样一个Mapping,靠我们手工的方式来定义每个stored procedure在一个真正的application是不现实的,一般地这些都是通过我们根据具体的Mapping关系开发的生成器生成的。像本Sample的所有stored procedure和trigger也都是通过Generator生成的。
下面是整个Helper class的实现,不算太复杂,有兴趣的话可以看看。否则敬请略过。
二.定义Dataset
我们根据数据库中Table的结构定义一个具有相同结构的strongly typed dataset:OrderDataSet.
![](https://i-blog.csdnimg.cn/blog_migrate/1475dea52c8d87e448a334ed7d6075d3.jpeg)
为了保证数据的完整性,我们必须为两表的relation做出如下的设置:
![](https://i-blog.csdnimg.cn/blog_migrate/2b6ea447326cbb2471a52ee93a44766f.jpeg)
同时我们为Log的数据定义下面的一个strongly typed dataset:AuditLoggingDataSet。该Dataset中只包含一个Table: T_AUDIT_LOG。我们之所以没有定义T_AUDIT_LOG_DETAIL是因为T_AUDIT_LOG_DETAIL中的数据是通过trigger添加的,我们同过程序只需要在主表中添加总体信息就可以了。
![](https://i-blog.csdnimg.cn/blog_migrate/358710db90b9be6acf3137dbd1b8470f.jpeg)
三、定义用于Audit log的helper class:AuditLoggingHelper
下面是所有AuditLoggingHelper所有的Code,很简单。我分别定义了一个public的property:AuditLoggingData。其类型为我们上面定义的strongly typed dataset:AuditLoggingDataSet。还定义了一个Public 的方法AuditLog向AuditLoggingData中添加Log信息,并返回一个Guid用以标识将要执行的transaction。我管这个Guid为Transaction no。
using System;
using System.Collections.Generic;
using System.Text;
namespace Artech.AuditLogging.ConsoleApp
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
public class AuditLoggingHelper
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
private AuditLoggingDataSet _auditLoggingData;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
/// <summary>
/// A strongly typed dataset to used to store the general auditoing inforamtion.
/// </summary>
public AuditLoggingDataSet AuditLoggingData
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
get {
return _auditLoggingData; }
set { _auditLoggingData = value; }
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
/// <summary>
/// Log the general auditoing information according with the current transaction.
/// </summary>
/// <returns>A guid which identifies uniquely a transaction</returns>
public Guid AuditLog()
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
if (
this._auditLoggingData ==
null)
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
this._auditLoggingData =
new AuditLoggingDataSet();
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
Guid transactionNo = Guid.NewGuid();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
AuditLoggingDataSet.T_AUDIT_LOGRow auditRow=
this._auditLoggingData.T_AUDIT_LOG.NewT_AUDIT_LOGRow();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
auditRow.BeginEdit();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
auditRow.TRANSACTION_NO = transactionNo.ToString();
//TODO: The user id is generally the account of the current login user.
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
auditRow.USER_ID = "testUser";
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
auditRow.OPERATION_DATE = DateTime.Now;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
auditRow.EndEdit();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
this._auditLoggingData.T_AUDIT_LOG.AddT_AUDIT_LOGRow(auditRow);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
return transactionNo;
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
}
四、定义stored procedure和trigger
为了较为真实地贴近我们现实的开发, 本Sample的所有Data access操作(除了data retrieval外)均采用stored procedure。通过所有需要进行Log的详细地信息都是通过Trigger来添加的。所有的stored procedure通过这里来查看,所有的trigger通过这里查看。
五:模拟Insert操作
我们先清空所有的Log数据,通过下面的方法添加一个新的Order。
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
namespace Artech.AuditLogging.ConsoleApp
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
class Program
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
static string USER_ID = "testUser";
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
static void Main(
string[] args)
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
AddOrderData();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
Console.WriteLine("Operation completes!");
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
Console.Read();
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
static void UpdateCommonField(DataRow row)
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
row["LAST_UPDATED_BY"] = USER_ID;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
row["LAST_UPDATED_ON"] = DateTime.Now;
if (row.RowState == DataRowState.Detached || row.RowState == DataRowState.Added)
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
row["CREATED_BY"] = USER_ID;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
row["CREATED_ON"] = DateTime.Now;
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
static void AddOrderData()
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
AuditLoggingHelper auditLoggingHelper =
new AuditLoggingHelper();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
Guid transactionNo = auditLoggingHelper.AuditLog();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
//Add an order item
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
OrderDataSet orderData =
new OrderDataSet();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
OrderDataSet.T_ORDERRow orderRow = orderData.T_ORDER.NewT_ORDERRow();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.BeginEdit();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.ORDER_DATE = DateTime.Today;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.SUPPLIER = "HP Corporation";
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
UpdateCommonField(orderRow);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.TRANSACTION_NO = transactionNo.ToString();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.EndEdit();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderData.T_ORDER.AddT_ORDERRow(orderRow);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
//Add two order detail items.
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
OrderDataSet.T_ORDER_DETAILRow orderDetailRow = orderData.T_ORDER_DETAIL.NewT_ORDER_DETAILRow();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.BeginEdit();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.ORDER_ID = orderRow.ORDER_ID;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.PRODUCT_ID = 1;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.PRODUCT_NAME = "HP Printer";
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.UNIT_PRICE = 3000;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.QUANTITY = 2;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
UpdateCommonField(orderDetailRow);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.TRANSACTION_NO = transactionNo.ToString();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.EndEdit();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderData.T_ORDER_DETAIL.AddT_ORDER_DETAILRow(orderDetailRow);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow = orderData.T_ORDER_DETAIL.NewT_ORDER_DETAILRow();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.BeginEdit();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.ORDER_ID = orderRow.ORDER_ID;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.PRODUCT_ID = 2;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.PRODUCT_NAME = "HP PC";
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.UNIT_PRICE = 3400;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.QUANTITY = 22;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
UpdateCommonField(orderDetailRow);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.TRANSACTION_NO = transactionNo.ToString();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.EndEdit();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderData.T_ORDER_DETAIL.AddT_ORDER_DETAILRow(orderDetailRow);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
using (DataAccessHelper dataAccessHelper =
new DataAccessHelper())
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.BeginTransaction();
try![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.UpdateData(auditLoggingHelper.AuditLoggingData.T_AUDIT_LOG);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.UpdateData(orderData.T_ORDER);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.UpdateData(orderData.T_ORDER_DETAIL);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.Commit();
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
catch(Exception ex)
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.Rollback();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
Console.WriteLine(ex.Message);
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
}
我们来看看T_AUDIT_LOG的记录:
![](https://i-blog.csdnimg.cn/blog_migrate/ccdb34f26450182829388b38f00c34c3.jpeg)
T_AUDIT_LOG_DETAIL的记录
![](https://i-blog.csdnimg.cn/blog_migrate/f7b37893d1b92aabb081bb3d9aec3cdb.jpeg)
DATA_CHANGE的data分别为下面3段XML。
<
dataChange
>
<
after
order_id
="33"
order_date
="Apr 23 2007 12:00AM"
supplier
="HP Corporation"
/>
</
dataChange
>
<
dataChange
>
<
after
order_id
="33"
product_id
="1"
product_name
="HP Printer"
unit_price
="3000.00"
quantity
="2"
/>
</
dataChange
>
<
dataChange
>
<
after
order_id
="33"
product_id
="2"
product_name
="HP PC"
unit_price
="3400.00"
quantity
="22"
/>
</
dataChange
>
六、模拟Update操作
定义新的方法UpdateOrderData修改我们刚刚添加的Order记录:
static
void UpdateOrderData()
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
OrderDataSet orderData = GetAllOrderData();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
AuditLoggingHelper auditLoggingHelper =
new AuditLoggingHelper();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
Guid transactionNo = auditLoggingHelper.AuditLog();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
OrderDataSet.T_ORDERRow orderRow = orderData.T_ORDER[0];
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.ORDER_DATE =
new DateTime(2005, 1, 1);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.SUPPLIER = "Dell Corporation";
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.TRANSACTION_NO = transactionNo.ToString();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
UpdateCommonField(orderRow);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
OrderDataSet.T_ORDER_DETAILRow orderDetailRow = orderData.T_ORDER_DETAIL[0];
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.PRODUCT_ID = 3;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.PRODUCT_NAME = "Workstation";
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.UNIT_PRICE = 10000;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.QUANTITY = 1;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.TRANSACTION_NO = transactionNo.ToString();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
UpdateCommonField(orderDetailRow);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
using (DataAccessHelper dataAccessHelper =
new DataAccessHelper())
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.BeginTransaction();
try![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.UpdateData(auditLoggingHelper.AuditLoggingData.T_AUDIT_LOG);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.UpdateData(orderData.T_ORDER);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.UpdateData(orderData.T_ORDER_DETAIL);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.Commit();
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
catch (Exception ex)
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.Rollback();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
Console.WriteLine(ex.Message);
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
}
执行上面的方法,然后查看我们Log表的记录。
![](https://i-blog.csdnimg.cn/blog_migrate/4c212b05e68934801fa36d94c6528199.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/963dea18386080f5421e6da2f96bc1fa.jpeg)
两条Update记录对应的DATA_CHANGE字段的XML分别为:
<
dataChange
>
<
before
order_id
="33"
order_date
="Apr 23 2007 12:00AM"
supplier
="HP Corporation"
/>
<
after
order_id
="33"
order_date
="Jan 1 2005 12:00AM"
supplier
="Dell Corporation"
/>
</
dataChange
>
<
dataChange
>
<
before
order_id
="33"
product_id
="1"
product_name
="HP Printer"
unit_price
="3000.00"
quantity
="2"
/>
<
after
order_id
="33"
product_id
="1"
product_name
="Workstation"
unit_price
="10000.00"
quantity
="1"
/>
</
dataChange
>
七、模拟Delete操作
定于DeleteOrderData方法delete掉我们添加的Order记录:
static
void DeleteOrderData()
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
OrderDataSet orderData = GetAllOrderData();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
AuditLoggingHelper auditLoggingHelper =
new AuditLoggingHelper();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
Guid transactionNo = auditLoggingHelper.AuditLog();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
//Delete two order detail items.
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
OrderDataSet.T_ORDER_DETAILRow orderDetailRow = orderData.T_ORDER_DETAIL[0];
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.TRANSACTION_NO = transactionNo.ToString();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.AcceptChanges();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.Delete();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow = orderData.T_ORDER_DETAIL[1];
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.TRANSACTION_NO = transactionNo.ToString();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.AcceptChanges();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderDetailRow.Delete();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
//Delete the order item.
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
OrderDataSet.T_ORDERRow orderRow = orderData.T_ORDER[0];
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.TRANSACTION_NO = transactionNo.ToString();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.AcceptChanges();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
orderRow.Delete();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
using (DataAccessHelper dataAccessHelper =
new DataAccessHelper())
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.BeginTransaction();
try![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.UpdateData(auditLoggingHelper.AuditLoggingData.T_AUDIT_LOG);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.UpdateData(orderData.T_ORDER_DETAIL);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.UpdateData(orderData.T_ORDER);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.Commit();
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
catch (Exception ex)
![ExpandedSubBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
dataAccessHelper.Rollback();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
Console.WriteLine(ex.Message);
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
}
执行上面的方法,然后查看我们Log表的记录。
![](https://i-blog.csdnimg.cn/blog_migrate/1138aee10d4aac04d5fbdb81b40012b8.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/b02b27c321f9ed5e775bb7f6ade850f6.jpeg)
三条Delete记录对应的DATA_CHANGE字段的XML分别为:
<
dataChange
>
<
before
order_id
="33"
product_id
="1"
product_name
="Workstation"
unit_price
="10000.00"
quantity
="1"
/>
</
dataChange
>
<
dataChange
>
<
before
order_id
="33"
product_id
="2"
product_name
="HP PC"
unit_price
="3400.00"
quantity
="22"
/>
</
dataChange
>
<
dataChange
>
<
before
order_id
="33"
order_date
="Jan 1 2005 12:00AM"
supplier
="Dell Corporation"
/>
</
dataChange
>