2017-10-09 137 views
0

我想列出報價的報價行,同時保持通用接口足夠通用,以便能夠類似地顯示其他實體。Dynamics CRM C#SDK - 嘗試獲取Quote Line的名稱,但字段不存在?

爲了做到這一點,我試圖使用EntityMetadata中的PrimaryNameAttribute。適用於大多數實體,但對於QuoteDetail,PrimaryNameAttribute是「productidname」 - 實際上並不作爲QuoteDetail實體的一部分存在的屬性。

此字段「productidname」也是其他實體(OpportunityProduct,SalesOrderDetail)的PrimaryNameAttribute,在這些情況下該字段也缺失。

什麼給?我覺得我已經搜索了所有的谷歌,似乎沒有人遇到過這個問題,所以,也許我錯過了一些簡單的東西。

這是MSDN的QuoteDetail實體頁面,顯示了我在說的內容:https://msdn.microsoft.com/en-us/library/mt607959.aspx請注意,PrimaryNameAttribute未在頁面的任何其他位置列出。

回答

1

QuoteDetail(喜歡的SalesOrderDetail和OpportunityProduct)是特殊的,因爲它可以是關係實體的目錄產品項目或寫在項目,無論從productidname(產品目錄從)或productdescription得到它的「名」(直寫在產品中)。您需要加入相關產品以獲取其名稱。

如果您即將開發通用解決方案/接口,這是您需要解決的每個查找屬性的問題。

如果你永遠只能從連接在查找記錄需要的PrimaryNameAttribute,您可以從FormattedValues收集你的「主」實體檢索名稱:

string productname = quotedetail.FormattedValues["productid"]; 

但更好/更安全:

string productname; 
quotedetail.FormattedValues.TryGetValue("productid", out productname); 

處理任意實體的屬性可能如下所示:

foreach (var key in record.Attributes.Keys) 
{ 
    if (record.FormattedValues.ContainsKey(key)) 
    { 
     string formattedvalue; 

     if (record.FormattedValues.TryGetValue(key, out formattedvalue)) 
     { 
      Console.WriteLine(formattedvalue); // use formattedvalue string 
     } 

     continue; // skip to next field when found in formatted values 
    } 

    object attributevalue; 

    record.Attributes.TryGetValue(key, out attributevalue); 

    object actualvalue; 
    string actualtext = string.Empty; 

    // handle AliasedValue fields from JOINed/LinkEntities 
    if (attributevalue.GetType().Name == "AliasedValue") 
    { 
     actualvalue = ((AliasedValue)attributevalue).Value; 
    } 
    else 
    { 
     actualvalue = attributevalue; 
    } 

    switch (actualvalue.GetType().Name) 
    { 
     case "EntityReference": 
      actualtext = ((EntityReference)actualvalue).Name; // this will catch Lookup values not contained in FormattedValues when you just created them 
      break; 

     case "DateTime": 
      actualtext = string.Format("{0:dd.MM.yyyy}", ((DateTime)actualvalue).ToLocalTime()); // ... any other dateTime format you'd like 
      break; 

     case "Guid": 
      actualtext = string.Format("{0:D}", actualvalue); // Entity Primary key 
      break; 

     default: 
      actualtext = (string)actualvalue; // anything else 
      break; 
    } 

    Console.WriteLine(actualtext); 
} 

您仍然需要照顧新分配的OptionSetValueMoney屬性(類似於EntityReference),因爲這些屬性通常會從FormattedValues中提取。

由於本示例處理的是現有的crm數據,因此您需要了解您的實體可能不包含所有屬性的缺陷,因此您可能需要重複執行.Attributes.Keys的預定義屬性名稱集合。

我的個人策略通常是創建一個輕量級ORM來在類型化對象和CRM實體之間進行映射,但這不符合您對通用接口的要求。


對於像你這樣的情況下,它是非此即彼的屬性,我把語法糖的工作:

string pn = qd.GetAttributeValue<string>("productdesription") ?? (qd.GetAttributeValue<EntityReference>("productid") ?? new EntityReference { Name = string.Empty }).Name; 

嘗試獲得寫在產品名稱;如果它爲空,嘗試獲取Lookup名稱,如果它爲null,則從假EntityReference中獲取一個空字符串。

這允許無摩擦的編碼,很好地解決了「這個或那個屬性」。

+0

好的,謝謝。元數據中是否有可以指導我的代碼根據需要引入相關實體/字段的內容?或者這是我需要硬編碼到我的解決方案,以涵蓋違規實體? – Yoni

+0

剛剛看到您的更新。很快就會嘗試。再次感謝。 – Yoni

+0

更新示例應該給你一個總體思路。我將添加完整的代碼示例,介紹如何隨後提取任意屬性。 – Filburt