MS Dynamics 365 C# 审计历史 KeyNotFoundException
MS Dynamics 365 C# audit history KeyNotFoundException
我正在尝试提取特定帐户的审核历史记录,如此处示例所示:
我特别需要提取名为 Credit Limit 的已更改字段的所有结果。
为了做到这一点,我在 C# 中编写了以下代码:
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Tooling.Connector;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PowerApps.Samples
{
public partial class SampleProgram
{
[STAThread] // Added to support UX
static void Main(string[] args)
{
CrmServiceClient service = null;
service = SampleHelpers.Connect("Connect");
if (!service.IsReady)
Console.WriteLine("No Connection was Made.");
Console.WriteLine("Connected");
//Create a new RetrieveAttributeChangeHistoryRequest
RetrieveAttributeChangeHistoryRequest req = new RetrieveAttributeChangeHistoryRequest();
//Set the target Entity
req.Target = new EntityReference("new_case", new Guid("468f8db5-4f98-eb11-57ee-0006ffc2587a"));
//Set the attribute you want to retrieve specifically
req.AttributeLogicalName = "credit_limit";
//Execute the request against the OrgService
RetrieveAttributeChangeHistoryResponse resp = (RetrieveAttributeChangeHistoryResponse)service.Execute(req);
AuditDetailCollection details = resp.AuditDetailCollection;
Console.WriteLine("Before the loop");
//Iterate through the AuditDetails
foreach (var detail in details.AuditDetails)
{
Console.WriteLine("Inside the loop");
//Important: the AuditDetailCollection.AuditDetails doesn’t always contain the type of AttributeAuditDetail, so make sure it is of correct type before casting
if (detail.GetType() == typeof(AttributeAuditDetail))
{
AttributeAuditDetail attributeDetail = (AttributeAuditDetail)detail;
String oldValue = "(no value)", newValue = "(no value)";
if (attributeDetail.OldValue.Contains("credit_limit"))
Console.WriteLine("old value: "+oldValue);
oldValue = attributeDetail.OldValue["credit_limit"].ToString();
if (attributeDetail.NewValue.Contains("credit_limit"))
Console.WriteLine("new value: "+newValue);
newValue = attributeDetail.NewValue["credit_limit"].ToString();
//TODO: Use the old value and new value in the Business Logic
}
}
Console.WriteLine("After the loop");
Console.ReadLine();
}
}
}
我在命令行中得到以下结果:
Connected
Before the loop
Inside the loop
old value: (no value)
new value: (no value)
Inside the loop
然后它因异常而中断,在 Visual Studio 中告诉我
System.Collections.Generic.KeyNotFoundExemption: The given key was not present in the dictionary.
有人可以澄清我做错了什么以及我可以做些什么来解决它吗?
问题是您正在检查“新值”和“旧值”是否包含您的属性,然后尝试使用它,即使它是假的。
我对您的代码稍作修改,它按预期运行。
//Create a new RetrieveAttributeChangeHistoryRequest
RetrieveAttributeChangeHistoryRequest req = new RetrieveAttributeChangeHistoryRequest();
//Set the target Entity
req.Target = new EntityReference("new_case", new Guid("468f8db5-4f98-eb11-57ee-0006ffc2587a"));
//Set the attribute you want to retrieve specifically
req.AttributeLogicalName = "credit_limit";
//Execute the request against the OrgService
RetrieveAttributeChangeHistoryResponse resp = (RetrieveAttributeChangeHistoryResponse)crmService.Execute(req);
AuditDetailCollection details = resp.AuditDetailCollection;
Console.WriteLine("Before the loop");
//Iterate through the AuditDetails
foreach (var detail in details.AuditDetails)
{
Console.WriteLine("Inside the loop");
//Important: the AuditDetailCollection.AuditDetails doesn’t always contain the type of AttributeAuditDetail, so make sure it is of correct type before casting
if (detail.GetType() == typeof(AttributeAuditDetail))
{
AttributeAuditDetail attributeDetail = (AttributeAuditDetail)detail;
String oldValue = "(no value)", newValue = "(no value)";
if (attributeDetail.OldValue.Contains("credit_limit"))
oldValue = attributeDetail.OldValue["credit_limit"].ToString();
Console.WriteLine("old value: " + oldValue);
if (attributeDetail.NewValue.Contains("credit_limit"))
newValue = attributeDetail.NewValue["credit_limit"].ToString();
Console.WriteLine("new value: " + newValue);
//TODO: Use the old value and new value in the Business Logic
}
}
Console.WriteLine("After the loop");
Console.ReadLine();
如果要根据 if
条件执行多个语句,则必须将 {}
中的语句分组。
if (attributeDetail.OldValue.Contains("credit_limit"))
{
oldValue = attributeDetail.OldValue["credit_limit"].ToString();
Console.WriteLine("old value: " + oldValue);
}
我正在尝试提取特定帐户的审核历史记录,如此处示例所示:
我特别需要提取名为 Credit Limit 的已更改字段的所有结果。
为了做到这一点,我在 C# 中编写了以下代码:
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Tooling.Connector;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PowerApps.Samples
{
public partial class SampleProgram
{
[STAThread] // Added to support UX
static void Main(string[] args)
{
CrmServiceClient service = null;
service = SampleHelpers.Connect("Connect");
if (!service.IsReady)
Console.WriteLine("No Connection was Made.");
Console.WriteLine("Connected");
//Create a new RetrieveAttributeChangeHistoryRequest
RetrieveAttributeChangeHistoryRequest req = new RetrieveAttributeChangeHistoryRequest();
//Set the target Entity
req.Target = new EntityReference("new_case", new Guid("468f8db5-4f98-eb11-57ee-0006ffc2587a"));
//Set the attribute you want to retrieve specifically
req.AttributeLogicalName = "credit_limit";
//Execute the request against the OrgService
RetrieveAttributeChangeHistoryResponse resp = (RetrieveAttributeChangeHistoryResponse)service.Execute(req);
AuditDetailCollection details = resp.AuditDetailCollection;
Console.WriteLine("Before the loop");
//Iterate through the AuditDetails
foreach (var detail in details.AuditDetails)
{
Console.WriteLine("Inside the loop");
//Important: the AuditDetailCollection.AuditDetails doesn’t always contain the type of AttributeAuditDetail, so make sure it is of correct type before casting
if (detail.GetType() == typeof(AttributeAuditDetail))
{
AttributeAuditDetail attributeDetail = (AttributeAuditDetail)detail;
String oldValue = "(no value)", newValue = "(no value)";
if (attributeDetail.OldValue.Contains("credit_limit"))
Console.WriteLine("old value: "+oldValue);
oldValue = attributeDetail.OldValue["credit_limit"].ToString();
if (attributeDetail.NewValue.Contains("credit_limit"))
Console.WriteLine("new value: "+newValue);
newValue = attributeDetail.NewValue["credit_limit"].ToString();
//TODO: Use the old value and new value in the Business Logic
}
}
Console.WriteLine("After the loop");
Console.ReadLine();
}
}
}
我在命令行中得到以下结果:
Connected
Before the loop
Inside the loop
old value: (no value)
new value: (no value)
Inside the loop
然后它因异常而中断,在 Visual Studio 中告诉我
System.Collections.Generic.KeyNotFoundExemption: The given key was not present in the dictionary.
有人可以澄清我做错了什么以及我可以做些什么来解决它吗?
问题是您正在检查“新值”和“旧值”是否包含您的属性,然后尝试使用它,即使它是假的。
我对您的代码稍作修改,它按预期运行。
//Create a new RetrieveAttributeChangeHistoryRequest
RetrieveAttributeChangeHistoryRequest req = new RetrieveAttributeChangeHistoryRequest();
//Set the target Entity
req.Target = new EntityReference("new_case", new Guid("468f8db5-4f98-eb11-57ee-0006ffc2587a"));
//Set the attribute you want to retrieve specifically
req.AttributeLogicalName = "credit_limit";
//Execute the request against the OrgService
RetrieveAttributeChangeHistoryResponse resp = (RetrieveAttributeChangeHistoryResponse)crmService.Execute(req);
AuditDetailCollection details = resp.AuditDetailCollection;
Console.WriteLine("Before the loop");
//Iterate through the AuditDetails
foreach (var detail in details.AuditDetails)
{
Console.WriteLine("Inside the loop");
//Important: the AuditDetailCollection.AuditDetails doesn’t always contain the type of AttributeAuditDetail, so make sure it is of correct type before casting
if (detail.GetType() == typeof(AttributeAuditDetail))
{
AttributeAuditDetail attributeDetail = (AttributeAuditDetail)detail;
String oldValue = "(no value)", newValue = "(no value)";
if (attributeDetail.OldValue.Contains("credit_limit"))
oldValue = attributeDetail.OldValue["credit_limit"].ToString();
Console.WriteLine("old value: " + oldValue);
if (attributeDetail.NewValue.Contains("credit_limit"))
newValue = attributeDetail.NewValue["credit_limit"].ToString();
Console.WriteLine("new value: " + newValue);
//TODO: Use the old value and new value in the Business Logic
}
}
Console.WriteLine("After the loop");
Console.ReadLine();
如果要根据 if
条件执行多个语句,则必须将 {}
中的语句分组。
if (attributeDetail.OldValue.Contains("credit_limit"))
{
oldValue = attributeDetail.OldValue["credit_limit"].ToString();
Console.WriteLine("old value: " + oldValue);
}