目录
选项
设想
怎么运行的
审核历史记录是模型驱动的应用程序中出色的即装即用功能。但是,查询审核历史记录有些棘手。不幸的是,诸如Power Automate CDS连接器,LinQ或简单的FetchXml之类的常用查询机制不支持它。这篇文章将讨论我们拥有的选项和示例代码。
- 使用SDK消息RetrieveRecordChangeHistoryRequest和RetrieveRecordChangeHistoryResponse,本文中将对此进行介绍
- 使用Kingswaysoft的D365集成工具包(本文不涵盖)
我将查询审计历史记录中的联系实体记录,并读取其电子邮件地址属性的审计详细信息。审计详细信息可从以下四个方面获得:
- 变更日期
- 变更栏位
- 旧值
- 新值
如果启用了审核,则此代码将适用于几乎所有实体和属性。
怎么运行的我们需要实体的ID(GUID),并使用它们的ID来查询审核历史记录。我正在使用fetchxml查询来检索ID,但这可以是您选择的一种机制,具体取决于实现和要求。
var targetEntites_query = @"
";
通常,我们知道FetchXml最多可以返回5000个实体,但是即使结果中有5000条以上的记录,该代码也会处理并返回。
public List RetrieveAllRecords(string fetch)
{
var moreRecords = false;
int page = 1;
var cookie = string.Empty;
List Entities = new List();
do
{
var xml = string.Format(fetch, cookie);
var collection = CrmClient.RetrieveMultiple(new FetchExpression(xml));
if (collection.Entities.Count >= 0) Entities.AddRange(collection.Entities);
moreRecords = collection.MoreRecords;
if (moreRecords)
{
page++;
cookie = string.Format("paging-cookie='{0}' page='{1}'",
System.Security.SecurityElement.Escape(collection.PagingCookie), page);
}
} while (moreRecords);
return Entities;
}
提示:FetchXml查询必须具有{0},如果返回5000条以上的记录。如果需要,可以在fetch中添加其他列。
接下来,我遍历这些ID并使用以下代码读取记录的审核历史记录:
public AuditDetailCollection GetAuditHistory(string entityLogicalName, Guid recordId)
{
var changeRequest = new RetrieveRecordChangeHistoryRequest();
changeRequest.Target = new EntityReference(entityLogicalName, recordId);
var changeResponse =
(RetrieveRecordChangeHistoryResponse)this.CrmClient.Execute(changeRequest);
return changeResponse.AuditDetailCollection;
}
上面的函数返回AuditDetailCollection,其是一个AuditDetails集合。一个Audit细节代表审核历史记录中的一项。请注意,审核历史记录的顺序与它们在用户界面中出现的顺序相同(降序)。
每个审核详细信息记录的日期都会更改,并且将收集带有字段名称的新旧值,我们需要循环阅读这些值。
下面是实现此目的的代码:
//Collection of entities for which we are going to read audit history
var AllTargetEnteties = this.RetrieveAllRecords(targetEntites_query);
foreach (var targetComplaint in AllTargetEnteties)
{
//Now pass id(guid) of record with entity name to retrieve audit history
var audit_history_entries = this.GetAuditHistory
(targetComplaint.LogicalName, targetComplaint.Id);
foreach (AuditDetail auditDetail in audit_history_entries.AuditDetails)
{
if ((auditDetail.GetType())?.Name == "AttributeAuditDetail")
{
//Below code reads Changed Date
var changeDate =
auditDetail.AuditRecord.GetAttributeValue("createdon");
var newValueEntity = ((AttributeAuditDetail)auditDetail)?.NewValue;
if (newValueEntity.Attributes.Count > 0)
{
{
foreach (var attrNewValue in newValueEntity?.Attributes)
{
//Here, we will need to
//match attribute name to read new value.
//In this case, I'm reading emailaddress1
if (attrNewValue.Key == "emailaddress1")
{
var newEmailAddress = attrNewValue.Value;
//Custom Logic for New Value here
}
}
}
}
var oldValueEntity = ((AttributeAuditDetail)auditDetail)?.OldValue;
if (oldValueEntity.Attributes.Count > 0)
{
foreach (var attrOldValue in oldValueEntity?.Attributes)
{
//Here, we will need to match attribute name to read old value.
//In this case, I'm reading emailaddress1
if (attrOldValue.Key == "emailaddress1")
{
var oldEmailAddress = attrOldValue.Value;
//Custom logic for Old value will be here
}
}
}
}
}
}
希望对您有所帮助。
https://www.codeproject.com/Articles/5292977/Querying-Audit-History