Retrieve Current ID Crm Online - dynamics-crm-2011

Entity title = new Entity();
title = service.Retrieve("incident",((Guid)((Entity)context.InputParameters["Target"]).Id), new ColumnSet("title"));
I am using this code to get the current id of an Incident while i'am closing it!
But received this error :
Unexpected exception from plug-in (Execute): FecharIncidente.Plugins.PostIncidenteClose: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
One of my mates uses exactly the same code and is working on his crm !
Some help !?!

Apparently your InputParameters collection doesn't have a "Target" key value. Check that the request that you're using has a "Target" InputParameter.
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parameters.
title = service.Retrieve("incident", ((Entity)context.InputParameters["Target"]).Id, new ColumnSet("title"));

Bet you "Target" in not Contained in InputParameters, resulting in KeyNotFoundException - "The given key was not present in the dictionary."
your can check for Target like Daryl explained or use the context available from the workflow rather like so ...
protected override void Execute(CodeActivityContext executionContext)
{
// Create the context
var context = executionContext.GetExtension<IWorkflowContext>();
var title = new Entity();
//context.PrimaryEntityName - should hold string incident
//context.PrimaryEntityId - should hold your guid
title = service.Retrieve(context.PrimaryEntityName, context.PrimaryEntityId, new ColumnSet("title"));
}

Related

Acumatica GetList error: Optimization cannot be performed.The following fields cause the error: Attributes.AttributeID

Developer's version of Acumatica 2020R1 is installed locally. Data for sample tenant MyTenant from training for I-300 were loaded, and WSDL connection established.
DefaultSoapClient is created fine.
However, attempts to export any data by using Getlist cause errors:
using (Default.DefaultSoapClient soapClient =
new Default.DefaultSoapClient())
{
//Sign in to Acumatica ERP
soapClient.Login
(
"Admin",
"*",
"MyTenant",
"Yogifon",
null
);
try
{
//Retrieving the list of customers with contacts
//InitialDataRetrieval.RetrieveListOfCustomers(soapClient);
//Retrieving the list of stock items modified within the past day
// RetrievalOfDelta.ExportStockItems(soapClient);
RetrievalOfDelta.ExportItemClass(soapClient);
}
public static void ExportItemClass(DefaultSoapClient soapClient)
{
Console.WriteLine("Retrieving the list of item classes...");
ItemClass ItemClassToBeFound = new ItemClass
{
ReturnBehavior = ReturnBehavior.All,
};
Entity[] ItemClasses = soapClient.GetList(ItemClassToBeFound);
string lcItemType = "", lcValuationMethod = "";
int lnCustomFieldsCount;
using (StreamWriter file = new StreamWriter("ItemClass.csv"))
{
//Write the values for each item
foreach (ItemClass loItemClass in ItemClasses)
{
file.WriteLine(loItemClass.Note);
}
}
The Acumatica instance was modified by adding a custom field to Stock Items using DAC, and by adding several Attributes to Customer and Stock Items.
Interesting enough, this code used to work until something broke it.
What is wrong here?
Thank you.
Alexander
In the request you have the following line: ReturnBehavior = ReturnBehavior.All
That means that you try to retrieve all linked/detail entities of the object. Unfortunately, some object are not optimized enough to not affect query performance in GetList scenarios.
So, you have to options:
Replace ReturnBehavior=All by explicitly specifying linked/detail entities that you want to retrieve and not include Attributes into the list.
Retrieve StockItem with attributes one by one using Get operation instead of GetList.
P.S. The problem with attributes will most likely be fixed in the next version of API endpoint.
Edit:
Code sample for Get:
public static void ExportItemClass(DefaultSoapClient soapClient)
{
Console.WriteLine("Retrieving the list of item classes...");
ItemClass ItemClassToBeFound = new ItemClass
{
ReturnBehavior = ReturnBehavior.Default //retrieve only default fields (without attributes and other linked/detailed entities)
};
Entity[] ItemClasses = soapClient.GetList(ItemClassToBeFound);
foreach(var entity in ItemClasses)
{
ItemClass itemClass= entity as ItemClass;
ItemClass.ReturnBehavior=ReturnBehavior.All;
// retrieve each ItemClass with all the details/linked entities individually
ItemClass retrievedItemCLass = soapClient.Get(itemClass);
}

Linq queries and optionSet labels, missing formatted value

I'm doin a simple query linq to retrieve a label from an optionSet. Looks like the formatted value for the option set is missing. Someone knows why is not getting generated?
Best Regards
Sorry for the unclear post. I discovered the problem, and the reason of the missing key as formattedvalue.
The issue is with the way you retrieve the property. With this query:
var invoiceDetails = from d in xrmService.InvoiceSet
where d.InvoiceId.Value.Equals(invId)
select new
{
name = d.Name,
paymenttermscode = d.PaymentTermsCode
}
I was retrieving the correct int value for the option set, but what i needed was only the text. I changed the query this way:
var invoiceDetails = from d in xrmService.InvoiceSet
where d.InvoiceId.Value.Equals(invId)
select new
{
name = d.Name,
paymenttermscode = d.FormattedValues["paymenttermscode"]
}
In this case I had an error stating that the key was not present. After many attempts, i tried to pass both the key value and the option set text, and that attempt worked just fine.
var invoiceDetails = from d in xrmService.InvoiceSet
where d.InvoiceId.Value.Equals(invId)
select new
{
name = d.Name,
paymenttermscode = d.PaymentTermsCode,
paymenttermscodeValue = d.FormattedValues["paymenttermscode"]
}
My guess is that to retrieve the correct text associated to that option set, in that specific entity, you need to retrieve the int value too.
I hope this will be helpful.
Best Regards
You're question is rather confusing for a couple reasons. I'm going to assume that what you mean when you say you're trying to "retrieve a label from an OptionSet" is that you're attempting to get the Text Value of a particular OptionSetValue and you're not querying the OptionSetMetadata directly to retrieve the actual LocalizedLabels text value. I'm also assuming "formatted value for the option set is missing" is referring to the FormattedValues collection. If these assumptions are correct, I refer you to this: CRM 2011 - Retrieving FormattedValues from joined entity
The option set metadata has to be queried.
Here is an extension method that I wrote:
public static class OrganizationServiceHelper
{
public static string GetOptionSetLabel(this IOrganizationService service, string optionSetName, int optionSetValue)
{
RetrieveOptionSetRequest retrieve = new RetrieveOptionSetRequest
{
Name = optionSetName
};
try
{
RetrieveOptionSetResponse response = (RetrieveOptionSetResponse)service.Execute(retrieve);
OptionSetMetadata metaData = (OptionSetMetadata)response.OptionSetMetadata;
return metaData.Options
.Where(o => o.Value == optionSetValue)
.Select(o => o.Label.UserLocalizedLabel.Label)
.FirstOrDefault();
}
catch { }
return null;
}
}
RetrieveOptionSetRequest and RetrieveOptionSetResponse are on Microsoft.Xrm.Sdk.Messages.
Call it like this:
string label = service.GetOptionSetLabel("wim_continent", 102730000);
If you are going to be querying the same option set multiple times, I recommend that you write a method that returns the OptionSetMetadata instead of the label; then query the OptionSetMetadata locally. Calling the above extension method multiple times will result in the same query being executed over and over.

How to get id of saved entity

Dynamics CRM 2011 on premise
I can barely believe I can't find this out by Googling. MSDN is useless.
Here is some C# from a plugin:
integ_creditpayment creditpayment = new integ_creditpayment();
creditpayment.integ_Amount = totalPay;
//set more properties
context.AddObject(creditpayment);
context.SaveChanges();
Now I want to get the value of the id field in integ_creditpayment.
Can I get this immediately from creditpayment.id? (As in, does context.SaveChanges() cause the creditpayment variable to be updated with the new id?)
I'm assuming your real code is more complicated, but there is no need to use the context in your example code:
integ_creditpayment creditpayment = new integ_creditpayment();
creditpayment.integ_Amount = totalPay;
//set more properties
creditpayment.Id = service.Create(creditpayment);
You can also use a type initializer and get rid of your object all together if you'd like:
Guid id = service.Create(new integ_creditpayment
{
integ_Amount = totalPay;
});
service in this case is of type IOrganizationService
After the SaveChanges() you can get the record id with:
Guid justCreatedId = creditpayment.Id;

OrganizationServiceContext: System.InvalidOperationException: The context is already tracking the 'contact' entity

I'm trying to create a plugin that changes all related contacts' address fields if the parent account's address field is changed in account form. I created a plugin to run in pre operation stage (update message against account entity) synchronously.
I used LINQ query to retrieve all related contacts and it works. Then I'm using foreach loop to loop trough all contacts and change them address fields. I'm using OrganizationServiceContext.AddObject(); function to add every contact to the tracking pipeline (or whatever it's called) and finally I'm using OrganizationServiceContext.SaveChanges(); to trying to save all contacts. But that's when I'm getting this error:
System.InvalidOperationException: The context is already tracking the 'contact' entity.
Here's my code
// Updating child contacts' fields
if (context.PreEntityImages.Contains("preAccount") && context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) {
if (((Entity)context.InputParameters["Target"]).Contains("address2_name")) {
Entity account = (Entity)context.InputParameters["Target"];
Entity preAccount = (Entity)context.PreEntityImages["preAccount"];
if (account["address2_name"] != preAccount["address2_name"]) {
EntityReference parentCustomer = new EntityReference(account.LogicalName, account.Id);
Contact[] childContacts = orgService.ContactSet.Where(id => id.ParentCustomerId == parentCustomer).ToArray();
foreach (Contact contact in childContacts) {
contact.Address2_Name = (string)account["address2_name"];
orgService.AddObject(contact);
}
orgService.SaveChanges();
}
}
}
What I'm doing wrong?
You already attached the entities to the context when you retrieved the contacts with the query
Contact[] childContacts = orgService.ContactSet.Where(id => id.ParentCustomerId == parentCustomer).ToArray();
so you don't need to add again the entities to the context, instead you need to update them, by:
orgService.UpdateObject(contact); // this row instead of orgService.AddObject(contact);

Windows Azure: "An item with the same key has already been added." exception thrown on Select

I'm getting a strange error while trying to select a row from a table under Windows Azure Table Storage. The exception "An item with the same key has already been added." is being thrown even though I'm not inserting anything. The query that is causing the problem is as follows:
var ids = new HashSet<string>() { id };
var fields = new HashSet<string> {"#all"};
using (var db = new AzureDbFetcher())
{
var result = db.GetPeople(ids, fields, null);
}
public Dictionary<string, Person> GetPeople(HashSet<String> ids, HashSet<String> fields, CollectionOptions options)
{
var result = new Dictionary<string, Person>();
foreach (var id in ids)
{
var p = db.persons.Where(x => x.RowKey == id).SingleOrDefault();
if (p == null)
{
continue;
}
// do something with result
}
}
As you can see, there's only 1 id and the error is thrown right at the top of the loop and nothing is being modified.
However, I'm using "" as the Partition Key for this particular row. What gives?
You probably added an object with the same row key (and no partition key) to your DataServiceContext before performing this query. Then you're retrieving the conflicting object from the data store, and it can't be added to the context because of the collision.
The context tracks all object retrieved from the Tables. Since entities are uniquely identified by their partitionKey/rowKey combination, a context, like the tables, cannot contain duplicate partitionkey/rowkey combinations.
Possible causes of such a collison are:
Retrieving an entity, modifying it, and then retrieving it again using the same context.
Adding an entity to the context, and then retrieving one with the same keys.
In both cases, the context the encounters it's already tracking a different object which does however have the same keys. This is not something the context can sort out by itself, hence the exception.
Hope this helps. If you could give a little more information, that would be helpful.

Resources