Get the list of notes - c#

How to obtain the list (or e.g. collection) of guids of all notes associated with current entity?
I know that it is in some way connected with service.Retreive(...), but can't make working code.
Attach 1:
public void Execute(IServiceProvider serviceProvider)
{
Entity entity = null;
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (entity.Contains("new_parentopportunity"))
{
try
{
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
Guid projectGuid = entity.Id;
Guid oppGuid = ((EntityReference)entity["new_parentopportunity"]).Id;
for (int i = 0; i < 100; i++) //Instead of 100, I'll place obtained collection.Length
{
Entity opp = service.Retrieve("", oppGuid, new Microsoft.Xrm.Sdk.Query.ColumnSet(true)); //RETREIVE ENTITY NOTE HERE
var temop = CreateNoteAttachment(opp);
service.Create(temp);
}
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
}
}
}
private Entity CreateNoteAttachment(Entity oppNote)
{
//some code here
}
Update 1:
I also write it in queries, can you look at this, whethere everything fine there?
PasteBin

Two ways to query for related notes:
Early Bound:
var notes =
service.AnnotationSet.Where(annotation => annotation.Opportunity_Annotation.Id == entity.Id)
.Select(annotation => annotation.Id)
.ToList();
FetchXml:
var fetchXml = string.Format("<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>" +
"<entity name='annotation'>" +
"<attribute name='annotationid' />" +
"<filter type='and'>"+
"<condition attribute='objectid' operator='eq' value='{0}'/>"+
"</filter>"+
"</entity>" +
"</fetch>", entity.Id);
var response = service.RetrieveMultiple(new FetchExpression(fetchXml));
var notes = response.Entities;

Related

Micrsoft Dynamics CRM: Facing trouble while retrieving value from form

I am trying to get values from form and print those value in windows form but whenever I try to save the values it failed showing the error An unexpected error occurred from ISV code.
public void Execute(IServiceProvider serviceProvider) {
// Get the context and organization service
IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof (IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory) serviceProvider.GetService(typeof (IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
Entity target = context.InputParameters["Target"] as Entity;
try {
EntityReference lookupValue = target.GetAttributeValue < EntityReference > ("new_contact");
EntityReference lookupValue2 = target.GetAttributeValue < EntityReference > ("new_account");
// string contactname = target.GetAttributeValue<string>("new_contact");
// string accountname = target.GetAttributeValue<string>("new_account");
MessageBox.Show("" + lookupValue + " " + lookupValue2);
} catch (Exception ex) {
throw new InvalidPluginExecutionException(ex.Message);
}
}

CRM workflow: How to get all the records from a subgrid as a list of entities and perform multi-retrieve

As the title suggests, I do not know how to convert entity.attributes ["subgrid"] as a list of entities, on which to run the multiretrieve:
My code for now:
protected override void Execute(CodeActivityContext executionContext)
{
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
var entity = (Entity)context.InputParameters["Target"];
if (entity.LogicalName != "account")
{
return;
}
var currentAccountId = entity.Id;
try
{
if (!entity.Contains("Subgrid"))
{
return;
}
var itemsOnSubgrid = entity.Attributes["Subgrid"];
if(itemsOnSubgrid == null)
{
return;
}
else
{
//if subgrid exist and is not null
//List of entities needed
}
}
catch (Exception ex)
{
tracingService.Trace("MyWorkflow: {0}", ex.ToString());
throw new InvalidPluginExecutionException(ex.Message);
}
}
As you are writing code in a custom workflow assembly - the entity at this point does not know anything about the form it is being called from, and does not have a "Subgrid" property to allow you to access the related records.
You will need to do a sperate query to retrieve related contacts (as an example) using the target entity's "accountid" property to relate to the contacts' "parentcustomerid" property.
Assume you are looking for a method to get all associated records for a particular record.
If that is the case, I would have written something like this. Hope that helps.
private EntityCollection GetAssociatedRecords(string relationshipName, string relatedEntityName, string entityName, Guid entityId,OrganizationService service)
{
EntityCollection result = null;
try
{
QueryExpression query = new QueryExpression();
query.EntityName = relatedEntityName;
query.ColumnSet = new ColumnSet(false);
Relationship relationship = new Relationship();
relationship.SchemaName = relationshipName;
relationship.PrimaryEntityRole = EntityRole.Referencing;
RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();
relatedEntity.Add(relationship, query);
RetrieveRequest request = new RetrieveRequest();
request.RelatedEntitiesQuery = relatedEntity;
request.ColumnSet = new ColumnSet(true);
request.Target = new EntityReference
{
Id = entityId,
LogicalName = entityName
};
RetrieveResponse response = (RetrieveResponse)service.Execute(request);
RelatedEntityCollection relatedEntityCollection = response.Entity.RelatedEntities;
if (relatedEntityCollection.Count > 0)
{
if (relatedEntityCollection.Values.Count > 0)
{
result = (EntityCollection)relatedEntityCollection.Values.ElementAt(0);
}
}
}
catch (Exception exception)
{
throw exception;
}
return result;
}
In that based on the role of the other entity change the Primary Entity Role between Referencing and Referenced.
Hope that helps. Let me know if my assumption is wrong.

Delete message plug-in not firing Dynamics CRM

I have a parent entity and child entity. I'm creating a plugin to count number of child entities for each parent entity and display the number in noOfProduct field in parent entity. So every time when I created a new child entity, the value of number in noOfProduct will be increment to 1. But when I deleted the child entity, my plugin is not triggering, hence the value remain the same.
I registered my plugin,
step: create
primary entity: child_entity
event_pipeline: post-operation
synchronous
Plugin Images: post-image
This is my complete code.
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Description;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Client;
using System.Net;
using System.Web.Services;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NoOfProductsPlugin
{
public class NoOfProducts : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
//for create and update event
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parmameters.
Entity targetEntity = (Entity)context.InputParameters["Target"];
// Verify that the entity represents a connection.
if (targetEntity.LogicalName != "child_entity")
{
return;
}
else
{
try
{
//triggered upon create or update message
if (context.MessageName == "Create" || context.MessageName == "Update")
{
Entity postMessageImage;
Guid oppId = new Guid();
if (context.PostEntityImages.Contains("postMessageImage") && context.PostEntityImages["postMessageImage"] is Entity)
{
postMessageImage = (Entity)context.PostEntityImages["postMessageImage"];
oppId = ((EntityReference)postMessageImage.Attributes["lookup_fieldtoParent"]).Id;
}
//throw new InvalidPluginExecutionException
queryOppProd(service, oppId);
}
}
catch (FaultException<OrganizationServiceFault> ex)
{
throw new InvalidPluginExecutionException("An error occurred :-" + ex.Message, ex);
}
//</snippetFollowupPlugin3>
catch (Exception ex)
{
tracingService.Trace("An error occurred : {0}" + ex.Message, ex.ToString());
throw;
}
}
}
//for delete event use entityreference
else if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is EntityReference)
{
// Obtain the target entity from the input parmameters.
EntityReference targetEntity = (EntityReference)context.InputParameters["Target"];
// Verify that the entity represents a connection.
if (targetEntity.LogicalName != "child_entity")
{
return;
}
else
{
try
{
//triggered upon delete message
if (context.MessageName == "Delete")
{
Guid oppProdId = targetEntity.Id;
// retrieve oppid guid
Entity oppProd = new Entity("child_entity");
ColumnSet columns_ = new ColumnSet(new string[] { "lookup_fieldtoParent" });
oppProd = service.Retrieve(oppProd.LogicalName, oppProdId, columns_);
Guid oppId = new Guid();
oppId = ((EntityReference)oppProd["lookup_fieldtoParent"]).Id;
//throw new InvalidPluginExecutionException(
}
}
catch (FaultException<OrganizationServiceFault> ex)
{
throw new InvalidPluginExecutionException("An error occurred :-" + ex.Message, ex);
}
//</snippetFollowupPlugin3>
catch (Exception ex)
{
tracingService.Trace("An error occurred: {0}" + ex.Message, ex.ToString());
throw;
}
}
}
}
public void queryOppProd(IOrganizationService service, Guid oppId)
{
int noOfProduct = 0;
QueryExpression oppProdQuery = new QueryExpression { EntityName = "child_entity", ColumnSet = new ColumnSet("child_entityid", "lookup_fieldtoParent") };
oppProdQuery.Criteria.AddCondition("lookup_fieldtoParent", ConditionOperator.Equal, oppId); // to search for child_entity that linked to the selected parent_entity
EntityCollection oppProdQueryRetrieve = service.RetrieveMultiple(oppProdQuery);
if (oppProdQueryRetrieve != null && oppProdQueryRetrieve.Entities.Count > 0)
{
for (var i = 0; i < oppProdQueryRetrieve.Entities.Count; i++)
{
noOfProduct++;
}
}
//declare table used to retrieve the field and update
Entity opportunity = new Entity("parent_entity");
ColumnSet columns = new ColumnSet(new string[] { "new_noofproducts" });
opportunity = service.Retrieve(opportunity.LogicalName, oppId, columns);
opportunity["new_noofproducts"] = noOfProduct;
service.Update(opportunity);
}
public void queryOppProdOnDel(IOrganizationService service, Guid oppId, Guid oppProdId)
{
int noOfProduct = 0;
//query opportunityProduct by using opportunity guid
QueryExpression oppProdQuery = new QueryExpression { EntityName = "child_entity", ColumnSet = new ColumnSet("child_entityid", "lookup_fieldtoParent") };
FilterExpression oppProdQueryFilter = oppProdQuery.Criteria.AddFilter(LogicalOperator.And);
oppProdQueryFilter.AddCondition("child_entityid", ConditionOperator.NotEqual, oppProdId);
oppProdQueryFilter.AddCondition("lookup_fieldtoParent", ConditionOperator.Equal, oppId); // to search for child_entity that linked to the selected parent_entity
EntityCollection oppProdQueryRetrieve = service.RetrieveMultiple(oppProdQuery);
if (oppProdQueryRetrieve != null && oppProdQueryRetrieve.Entities.Count > 0)
{
for (var i = 0; i < oppProdQueryRetrieve.Entities.Count; i++)
{
noOfProduct++;
}
}
//throw new InvalidPluginExecutionException
//declare table used to retrieve the field and update
Entity opportunity = new Entity("parent_entity");
ColumnSet columns = new ColumnSet(new string[] { "new_noofproducts" });
opportunity = service.Retrieve(opportunity.LogicalName, oppId, columns);
service.Update(opportunity);
}
}
}
You forgot to call the method queryOppProdOnDel.
When you register your Plugin assembly & Step on Delete message, replace the below snippet in your code.
//triggered upon delete message
if (context.MessageName == "Delete")
{
Guid oppProdId = targetEntity.Id;
// retrieve oppid guid
Entity oppProd = new Entity("child_entity");
ColumnSet columns_ = new ColumnSet(new string[] { "lookup_fieldtoParent" });
oppProd = service.Retrieve(oppProd.LogicalName, oppProdId, columns_);
Guid oppId = new Guid();
oppId = ((EntityReference)oppProd["lookup_fieldtoParent"]).Id;
//throw new InvalidPluginExecutionException(
queryOppProdOnDel(service, oppId, oppProdId);
}
Update:
This line is missing in queryOppProdOnDel:
opportunity["new_noofproducts"] = noOfProduct;
Couple of points:
step: create You should register on delete.
Pretty sure post-image is not supported on delete. You need to use pre's. "The create operation doesn’t support a pre-image and a delete operation doesn’t support a post-image."
Your basic design has a flaw. If lots of changes occur at the same time, they could all execute concurrently on seperate threads, this means the count could be incorrect in some circumstances.

Create/Update method not allowed in "Activity Pointer" CRM 2011

Am having a plugin that moves the activities of lead to opportunity on qualify. I have registered the plugin on "Create" of opportunity and the following is the code
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
Entity entity;
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
entity = (Entity)context.InputParameters["Target"];
if (entity.Attributes.Contains("originatingleadid") == false) return;
}
else
{
return;
}
try
{
//.....
EntityReference Lead = (EntityReference)entity.Attributes["originatingleadid"];
Guid LeadGuid = Lead.Id;
MoveActivitiesFromLeadToOpportunity(service, LeadGuid, Opportunityid);
}
catch (FaultException<OrganizationServiceFault> ex)
{
throw new InvalidPluginExecutionException(
"An error occurred in the plug-in.", ex);
}
}
private void MoveActivitiesFromLeadToOpportunity(IOrganizationService service, Guid LeadID, Guid OpportunityID)
{
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "regardingobjectid";
condition.Operator = ConditionOperator.Equal;
condition.Values.Add(LeadID.ToString());
var query = new QueryExpression("activitypointer");
query.Criteria.AddCondition(condition);
//query.Conditions.Add("reagrdingobjectid", ConditionOperator.Equal, theIdOfTheRelatedRecord);
query.ColumnSet = new ColumnSet(true);
var activities = service.RetrieveMultiple(query).Entities;
foreach (var activity in activities)
{
var castedActivity = (ActivityPointer)activity;
if (castedActivity.ActivityTypeCode == "email")
{
castedActivity.Id = Guid.NewGuid();
castedActivity["regardingobjectid"] = new EntityReference("opportunity", OpportunityID);
//service.Create(castedActivity);--->Exception thrown
//service.Update(castedActivity);---->Tried this one too.Exception is thrown stating method not supported on "ActivityPointer"
}
}
Can somebody shed light on this? Am i missing something here? Thank you
You need to query for the exact entity type, because you can't update an activitypointer
private void MoveEmailsFromLeadToOpportunity(IOrganizationService service, Guid LeadID, Guid OpportunityID)
{
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "regardingobjectid";
condition.Operator = ConditionOperator.Equal;
condition.Values.Add(LeadID.ToString());
var query = new QueryExpression("email");
query.Criteria.AddCondition(condition);
query.ColumnSet = new ColumnSet(true);
var emails = service.RetrieveMultiple(query).Entities;
foreach (var email in emails)
{
email["regardingobjectid"] = new EntityReference("opportunity", OpportunityID);
service.Update(email);
}
}
you can also write a method that will retrieve first all the activities (as you already did) check the ActivityTypeCode after retrieve and update each single record depending on activity type (email, fax, ...)
Try commenting out this line:
castedActivity.Id = Guid.NewGuid();
And then just do your Update:
service.Update(castedActivity)
You are just updating the RegardingObjectId, not creating a new activity, so you shouldn't change the Id and you shouldn't use Create.

LINQ to SQL submitchanges not doing anything

My issue is the following: i'm trying to build a function to which i could pass a list of items, which would then go to the db with each of those items and update them. I believe the issue is within the way datacontexts are being used but i cannot figure out this issue.
Here is my function that builds the list of items that were changed:
protected void btnSave_Click(object sender, EventArgs e)
{
List<AFF_CMS_FMA> fmasToSave = new List<AFF_CMS_FMA>();
AFF_CMS_FMA newFmaItem = new AFF_CMS_FMA();
foreach (AFF_CMS_FMA fmaItem in FmaLib.fetchAllActiveAssetsInFMA())
{
if (fmaItem.SortOrder != Convert.ToInt32(Request.Form["fmaItem_" + fmaItem.ID + "_SortOrder"]))
{
newFmaItem = fmaItem;
newFmaItem.Name = SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_Name"]);
newFmaItem.AssetID = Convert.ToInt32(Request.Form["fmaItem_" + fmaItem.ID + "_AssetID"]);
newFmaItem.SortOrder = Convert.ToInt32(Request.Form["fmaItem_" + fmaItem.ID + "_SortOrder"]);
newFmaItem.ImagePathEn = SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_ImagePathEn"]);
newFmaItem.ImagePathCh = SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_ImagePathCh"]);
newFmaItem.StartDate = DateTime.Parse(SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_StartDate"]));
newFmaItem.EndDate = DateTime.Parse(SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_EndDate"]));
newFmaItem.ClickToUrl = SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_ClickToUrl"]);
fmasToSave.Add(newFmaItem);
}
}
FmaLib.saveEditedFmas(fmasToSave);
}
here is the function that the foreach loops calls to get all the items that are in the db:
public static List<AFF_CMS_FMA> fetchAllActiveAssetsInFMA()
{
List<AFF_CMS_FMA> results = null;
using (fmaDataContext db = new fmaDataContext())
{
using (TransactionScope ts = new TransactionScope())
{
try
{
if (HttpContext.Current.Cache["fmaActiveList"] == null)
{
db.LoadOptions = loadAll;
results = clsCompiledQuery.getAllActiveFmas(db).ToList();
HttpContext.Current.Cache["fmaActiveList"] = results;
}
else
results = (List<AFF_CMS_FMA>)HttpContext.Current.Cache["fmaActiveList"];
ts.Complete();
}
catch (Exception ex)
{ Transaction.Current.Rollback(); }
}
return results;
}
}
here are the queries being used:
protected static class clsCompiledQuery
{
public static Func<DataContext, IOrderedQueryable<AFF_CMS_FMA>>
getAllActiveFmas = CompiledQuery.Compile((DataContext db)
=> from fma in db.GetTable<AFF_CMS_FMA>()
where fma.IsArchived == false
orderby fma.SortOrder ascending
select fma);
public static Func<DataContext, int,IQueryable<AFF_CMS_FMA>>
getFmaById = CompiledQuery.Compile((DataContext db, int ID)
=> from fma in db.GetTable<AFF_CMS_FMA>()
where fma.ID == ID
select fma);
}
and finally this were im trying to get the save to happen to the db but no exeptions are throwns, yet the db does not change
public static bool saveEditedFmas(List<AFF_CMS_FMA> fmaToSaveList)
{
using (fmaDataContext db = new fmaDataContext())
{
using (TransactionScope ts = new TransactionScope())
{
try
{
foreach (AFF_CMS_FMA fmaItemToSave in fmaToSaveList)
{
AFF_CMS_FMA fmaItemToUpdate = clsCompiledQuery.getFmaById(db, fmaItemToSave.ID).ToList()[0];
fmaItemToUpdate = fmaItemToSave;
db.SubmitChanges();
}
return true;
}
catch (Exception ex)
{
Transaction.Current.Rollback();
return false;
}
}
}
}
I have checked and the table does contain a primary key in the designer. If i do the save from the btnSave_click function by passing a datacontext to the fetchAllActiveAssetsInFMA() then doing submitchanges on that context it works .. but im trying to abstract that from there.
thanks all in advance
Your not calling ts.Complete in function saveEditedFmas.
Also I would recommend calling db.SubmitChanges(); outside of the for loop. And why do you have a transaction in function fetchAllActiveAssetsInFMA? It's only fetching data right? And I'm not quite sure whats happening inside the for loop in save function, looks strange.
I think you should map the properties from fmaItemToSave to fmaItemToUpdate
foreach (var fmaItemToSave in fmaToSaveList)
{
var fmaItemToUpdate = clsCompiledQuery.getFmaById(db, fmaItemToSave.ID).First();
fmaItemToUpdate.Name = fmaItemToSave.Name;
fmaItemToUpdate.AssetID = fmaItemToSave.AssetID;
//And the rest of the properties
}
db.SubmitChanges();

Categories