如何在CRM Dynamics中使用别名属性时从fetchedXML访问值?

时间:2012-09-28 15:59:50

标签: c# dynamics-crm dynamics-crm-2011

我正在提取营销列表清单。正如我这样做,根据我使用intellisense的检查,这似乎是一次成功的操作。当我查找...Entities[0].Attributes["nick"]时,我得到一个对象(其中包含正确的数据)。但是我无法以编程方式访问它(相反,我必须通过插件点击一下,以便折叠好东西)。

事实上,我认为实体应该使用下面的代码。根据计算机,问题是它们不是Strings。它们的类型为Microsoft.Xrm.Sdk.AliasedValue,我不知道如何访问其中的实际缺口。

new Contact
{
  Name = element.Attributes["nick"] as String,
  Mail = element.Attributes["mail"] as String
}

Intellisense表示Value在那里(并且它也是正确的值)但我无法通过键入.Value来访问它。我怀疑我需要使用“as”或类似的东西,但此刻我被卡住了。任何提示? AsString null提供给我new Contact { Name = ((Microsoft.Xrm.Sdk.AliasedValue)result.Entities[0].Attributes["nick"]).Value, Mail = ((Microsoft.Xrm.Sdk.AliasedValue)result.Entities[0].Attributes["mail"]).Value } ...

我已经阅读了this article以及其他几个喜欢它和我看到它的方式,我应该能够访问那里所有有趣的东西。我不能......

我注意到以下代码为我提供了我非常想要获取的数据但是这个不能成为专业语法,可以吗?!说真的,它看起来像一个患有多动症和宿醉的高中生试图这样做......

{{1}}

我的意思是,认真 - 这是一段难看的代码......必须有更好的方法!但是,我担心不会因为this discussion似乎也在使用该语法......

3 个答案:

答案 0 :(得分:7)

查看documentionAttributes对象的Entity属性类型为AttributeCollection,其派生自DataCollection<string,Object>

  

对于集合中的每个属性,都有一个键/值对。

因此,对于每个密钥(“nick”,“mail”),都有一个对应的object,它可以是任何.NET类型。你将对象强制转换为正确的类型(正如你所做的那样)来访问你正在寻找的属性(或者使用反射,这肯定会更加丑陋,或者我认为在C#中4.0 dynamic type,但在这种情况下,您将失去编译时检查);编译器如何能够确定属性是string / Money / int / AliasedValue /等类型?

对于AliasedValue,CRM使用此类型存储有关返回值的其他信息,并且由于任何属性都可以别名,因此Value属性可以是任何类型({{1} },OptionSetValuedecimalstringGuid等)。 EntityReference属性也适当地类型为Value,因此您必须将其转换为获取有关返回值的任何其他信息。

因此无法进行强制转换,但您可以通过在文件顶部添加object语句并在定义之前定义每个using的值来缩短代码并使代码更清晰。分配给AliasedValue。无论如何,我已经包含了每种数据检索的一个例子;你可以判断你的项目哪个更好。

使用演员:

Contact

使用反射:

using Microsoft.Xrm.Sdk;

...

var nick = (AliasedValue)result.Entities[0].Attributes["nick"];
var mail = (AliasedValue)result.Entities[0].Attributes["mail"];

var contact = new Contact
{
    Name = nick.Value, //Value is of type object; cast again for a more specific type
    Mail = mail.Value
};

使用动态:

var nick = result.Entities[0].Attributes["nick"]
    .GetType()
    .GetProperty("Value")
    .GetValue(result.Entities[0].Attributes["nick"], null);
var mail = result.Entities[0].Attributes["mail"]
    .GetType()
    .GetProperty("Value")
    .GetValue(result.Entities[0].Attributes["mail"], null);

var contact = new Contact
{
    Name = nick,
    Mail = mail
};

答案 1 :(得分:1)

我想你想要这样的东西:

 //Get Account PrimaryContact details
        public static void GetAccountPrimaryContactDetails(Guid accountId, IOrganizationService orgService)
        {
            var contactFirstName = default(object);
            var contactLastName = default(object);
            var contactFullName = default(object);

            string fetchXML = string.Format(@"<fetch version='1.0' output-format='xml-platform' no-lock='true' mapping='logical'>
                                    <entity name='account'>
                                        <attribute name='name' />                                                                                
                                        <filter type='and'>
                                            <condition attribute='statuscode' operator='eq' value='1' />                                            
                                            <condition attribute='accountid' operator='eq' value='{0}' />
                                        </filter>                                        
                                        <link-entity name='contact' from='contactid' to='primarycontactid' alias='ab'>
                                             <attribute name='fullname' alias='as_fullname' />
                                             <attribute name='firstname' alias='as_firstname' />                                             
                                             <attribute name='lastname' alias='as_lastname' />
                                        </link-entity>
                                    </entity>
                                </fetch>", accountId.ToString());

            var fetchExp = new FetchExpression(fetchXML);

            EntityCollection accountEntity = orgService.RetrieveMultiple(fetchExp);

            if (accountEntity.Entities.Count > 0)
            {
                //Primary Contact Fullname
                AliasedValue avContactFullname = accountEntity.Entities[0].GetAttributeValue<AliasedValue>("as_fullname");
                if (avContactFullname != null)
                    contactFullName = avContactFullname.Value;
                //Primary Contact Firstname
                AliasedValue avContactFirstname = accountEntity.Entities[0].GetAttributeValue<AliasedValue>("as_firstname");
                if (avContactFirstname != null)
                    contactFirstName = avContactFirstname.Value;
                //Primary Contact Lastname
                AliasedValue avContactLastname = accountEntity.Entities[0].GetAttributeValue<AliasedValue>("as_lastname");
                if (avContactLastname != null)
                    contactLastName = avContactLastname.Value;

答案 2 :(得分:0)

我们定义了一个GetValue辅助函数来处理为你检查别名值

public static T GetValue<T>(this Entity entity, string attributeName)
{
     if (entity.Attributes.ContainsKey(attributeName))
    {
        var attr = entity[attributeName];
        if (attr is AliasedValue)
        {
            return GetAliasedValueValue<T>(entity, attributeName);
        }
        else
        {
            return entity.GetAttributeValue<T>(attributeName);
        }
    }
    else
    {
        return default(T);
    }

}

这使用内部额外辅助方法来获取别名字段值

private static T GetAliasedValueValue<T>(this Entity entity, string attributeName)
        {
            var attr = entity.GetAttributeValue<AliasedValue>(attributeName);
            if (attr != null)
            {
                return (T)attr.Value;
            }
            else
            {
                return default(T);
            }

        }

它被定义为Entity类的扩展方法,因此您可以像SDK提供的GetAttributeValue一样使用它 - 您只需记住使用别名字段名称。

var myValue = myEntity.GetValue<string>("alias.fieldname")