How can I get all the activities for an account? - c#

I have a program that I have written that gets the data from Dynamics CRM 2013 online. But I am running into one issue where a query to get the activities for an account only returns a subset instead of all the activities. The query expression is this
private QueryExpression CreateActivityQuery(Guid id)
{
QueryExpression query = new QueryExpression()
{
Distinct = true,
EntityName = Cd2Sf.ActivityPointer.EntityLogicalName,
ColumnSet = new ColumnSet(true)
};
query.Criteria = new FilterExpression();
query.Criteria.AddCondition("regardingobjectid", ConditionOperator.Equal, id);
return query;
}
Where the id is the account id. I had first tried using the activityparty where the party id was equal to the account id and then I tried using the regardingobjectid and lastly then tried the Rollup method with the extended related entities but all produce the same result.
#region Create RollupRequest
// Create RollupRequest
RollupRequest rollupRequest = new RollupRequest();
rollupRequest.Query = qexp;
rollupRequest.Target = new EntityReference("account", acct.Id);
rollupRequest.RollupType = RollupType.Extended;
#endregion Create RollupRequest
#region Execute RollupRequest
// Execute RollupRequest
RollupResponse rollupResponse = (RollupResponse)service.Execute(rollupRequest);
#endregion Execute RollupRequest
#region Show RollupResponse results
ShowActivities(rollupResponse.EntityCollection, percent);
#endregion Show RollupResponse results
Do I need to use contacts as well to get all the activities that are associated to the account, i.e. use the activityparty and match the to/from/sender/cc/bcc/etc with contacts for an account? I had tried to use the contact id as the regardingobjectid but that still does not account for all of the activities.
It appears that the web page for dynamics crm online when viewing the account and the activities that are on that page are more than what the above query gets alone.
How do I get the other activities, the ones that seem to be not directly related to the account?

My original answer doesn't answer the question - I've abbreviated it here.
Sarah Champ's post on using outer joins in your fetchxml is really good:
http://blogs.msdn.com/b/crminthefield/archive/2013/07/01/dynamic-activity-reporting-using-fetchxml.aspx
You have to use a FetchExpression rather than a QueryExpression, but you can use it the same way with a RetrieveMultipleRequest now.
FetchExpression example:
string fetch = "<fetch xml string>"
var query = new FetchExpression(fetch);
var request = new RetrieveMultipleRequest();
request.Query = query;
var entities = ((RetrieveMultipleResponse)service.Execute(request)).EntityCollection.Entities;
foreach (var entity in entities)
{
Console.WriteLine(entity.GetAttributeValue<string>("subject"));
}

Related

Querying product/pricing information against Dynamics 365 tenant using the C# SDK

I am trying to query product related information in a Dynamics 365 tenant (Version 9.2.22101.170) and with Version 9.0.2.46 of the Microsoft.CrmSdk. Mostly I am interested in querying products by the product number to retrieve price information, but later on, I would introduce more parameters. The below is one of the many methods I've tried (I am aware I am projecting only the name for the time being, eventually I would require price information etc):
var cols = new ColumnSet(new String[] { "name" });
QueryByAttribute query = new QueryByAttribute("product");
query.ColumnSet = cols;
query.Attributes.AddRange("productnumber");
query.Values.AddRange("100002");
var results = service.RetrieveMultiple(query);
if (results != null)
{
var entities = results.Entities.ToList();
if (entities != null)
{
var productEnt = (Product)entities.FirstOrDefault();
Console.WriteLine(productEnt.Name);
}
}
This is the error message returned, on the RetrieveMultiple call:
The entity with a name = 'product' with namemapping = 'Logical' was not found in the MetadataCache. MetadataCacheDetails: ProviderType=Dynamic, StandardCache=True, IsLoadedInStagedContext = False, Timestamp=8343791, MinActiveRowVersion=8343791
The same message is returned when calling any other method. It's clear that the issue is not the query, or the columns being returned but the "product".
Sure enough, I am using the below method to get the list of entity names, and the word "Product" does not show up. I think this explains the error message.
public static EntityMetadata[] GetEntities(IOrganizationService organizationService)
{
Dictionary<string, string> attributesData = new Dictionary<string, string>();
RetrieveAllEntitiesRequest metaDataRequest = new RetrieveAllEntitiesRequest();
RetrieveAllEntitiesResponse metaDataResponse = new RetrieveAllEntitiesResponse();
metaDataRequest.EntityFilters = EntityFilters.Entity;
// Execute the request.
metaDataResponse = (RetrieveAllEntitiesResponse)organizationService.Execute(metaDataRequest);
var entities = metaDataResponse.EntityMetadata;
return entities;
}
Is this a permission issue? Do I need to do some extra loading prior to the query? How do you query product/pricing related information in a Dynamics 365 tenant?
I tried searching for related information online, but I was surprised to practically find almost nothing related to Products.
you are using QueryByAttribute rather you should be using QueryExpression
Try below query and it should help.
// Define Condition Values
var query_productnumber = "100002";
// Instantiate QueryExpression query
var query = new QueryExpression("product");
query.Distinct = true;
// Add columns to query.ColumnSet
query.ColumnSet.AddColumns("productid", "name");
// Define filter query.Criteria
query.Criteria.AddCondition("productnumber", ConditionOperator.Equal, query_productnumber);
var results = service.RetrieveMultiple(query);
if (results != null)
{
var entities = results.Entities.ToList();
if (entities != null)
{
var productEnt = (Product)entities.FirstOrDefault();
Console.WriteLine(productEnt.Name);
}
}

Get Marketing list ID by name

I am trying to get the id of a marketing list created in Microsoft Dynamics based on the list's name. I will then use the id to add crm contacts to the list (this I can do fine using the id of the list)
I can't find any instructions in the documentation that explains how to do this. I have tried the following code but i get the error that no entity by that name exists:
var request = new RetrieveRequest();
request.Target = new EntityReference("new list 1", listId);
RetrieveResponse response = _organizationService.Execute(request) as RetrieveResponse;
What I am ultimately trying to do is make it possible for an administrator of the crm to identify the marketing list that a user should be added to when they fill in a newsletter form on our website. I think it will be too much to ask them to find the guid of the marketing list (it took me a bit of work to find it myself)
can anyone share some code to either get the id of a list using the list name as the identifier or let me know if its possible to add a contact to a list using the list name instead of the id?
The following code gets all lists in Dynamics with a name of "new list 1". It then stores the Id of the first list returned if one or more matches were found, or Guid.Empty if no matches were found. In your scenario there should be always be one and only one match.
var query = new QueryExpression
{
EntityName = "list",
ColumnSet = new ColumnSet(false)
};
query.Criteria.AddCondition("name", ConditionOperator.Equal, "new list 1";
var matchingLists = _organizationService.RetrieveMultiple(query);
var defaultListId = matchingLists?.Entities.FirstOrDefault()?.Id ?? Guid.Empty;
To retrieve the entity record using RetrieveRequest, schema name of that entity (DB table) should be passed as first parameter and primary key (GUID) as second. For Marketing list it is list & listid. You should also mention ColumnSet.
request.Target = new EntityReference("list", listId);
But to achieve what you want, you have to use either querybyattribute or queryexpression, then RetrieveMultiple will help you to get the Id from name of list.
FilterExpression filter = new FilterExpression();
filter.FilterOperator = LogicalOperator.And;
filter.AddCondition(new ConditionExpression("name", ConditionOperator.Equal, "new list 1"));
QueryExpression query = new QueryExpression("list");
query.Criteria.AddFilter(filter);
var result = Context.SystemService.RetrieveMultiple(query);
After that use AddListMembersListRequest or AddMemberListRequest to add members to that list.
// Add a list of contacts to the marketing list.
var addMemberListReq = new AddListMembersListRequest
{
MemberIds = new[] { _contactIdList[0], _contactIdList[2] },
ListId = listId
};
_serviceProxy.Execute(addMemberListReq);

Can I return only specific properties of nested entities when using the LINQ provider for OData? (equivalent of $expand and $select)

I'm using the OData .NET Client against the Dynamics CRM Online Web API. I can fetch a single Account entity like this:
var context = new DataServiceContext(new Uri("https://myorg.crm4.dynamics.com/api/data/v8.1/"));
// I hook into the BuildingRequest event here to add my auth header token
var accountID = new Guid("8d4e3373-454f-e611-80dc-c4346bad506c");
var account = (from a in context.Accounts
where a.Accountid == accountID
select new Account {
Name = a.Name,
Createdby = a.Createdby
}).Single();
The resulting OData query string looks like this:
https://myorg.crm4.dynamics.com/api/data/v8.1/accounts(8d4e3373-454f-e611-80dc-c4346bad506c)?$expand=createdby&$select=name
This works fine and returns the Account with just its name. My "problem" is that it also returns the entire SystemUser entity and all of its properties and nests them in CreatedBy.
{
"#odata.context":"https://myorg.crm4.dynamics.com/api/data/v8.1/$metadata#accounts(name,createdby)/$entity",
"#odata.etag":"W/\"752336\"",
"name":"Test Account 01",
"accountid":"8d4e3373-454f-e611-80dc-c4346bad506c",
"createdby":{
"#odata.etag":"W/\"752039\"",
"ownerid":"11fd590a-6147-e611-80d8-c4346bad62c0",
"_queueid_value":"16fd590a-6147-e611-80d8-c4346bad62c0",
"_createdby_value":null,
... lots of other properties here ...
"address1_stateorprovince":null,
"displayinserviceviews":false,
"timezoneruleversionnumber":null
}
}
I want to return only specific properties of the SystemUser entity which would use an OData query like this (the important part is $expand=createdby($select=fullname)):
https://myorg.crm4.dynamics.com/api/data/v8.1/accounts(8d4e3373-454f-e611-80dc-c4346bad506c)?$expand=createdby($select=fullname)&$select=name
If I run the above query I now get the Account entity with just its name and for CreatedBy it only has the Fullname property of the SystemUser.
I can't find a way to do this in the initial LINQ query. I tried this and got errors:
var account = (from a in context.Accounts
where a.Accountid == accountID
select new Account {
Name = a.Name,
Createdby = new SystemUser { Fullname = a.Createdby.Fullname }
}).Single();
Is it possible to select just specific properties of nested entities rather than the whole thing?
It's not the end of the world to return the entire thing, I just like to return only the data I want if it can be helped.
Edit 17/08/2016: After some further troubleshooting it appears that creating a new SystemUser and populating only the full name property does actually generate the correct OData query string. If I run it manually I get the correct result. I still get errors running it through the OData Client model. The error is:
The expected property 'Createdby' could not be found while processing an entry. Check for null before accessing this property.
The property is not null, it can't be by definition. I think it might be looking for CreatedBy on the SystemUser entity rather than on Account, but I'm not sure.

Retrieve Filter Conditions in Views in CRM 2011 using query expression (C#)

Am developing a windows form which resembles the look up view on CRM 2011.
For this I do the following
1) Show the relevant records (of opportunity entity) in a datagirdview
2) Also have a dropdownlist that binds to the views (View.Name) to allow the user to choose the view according to which i intend to change the filter on my datagrid view.
Am stuck with the following.Am able to retrieve the views on the "Opporutunity" entity using the following code
ConditionExpression condition1 = new ConditionExpression()
{
AttributeName = "querytype",
Operator = ConditionOperator.Equal,
Values = { 0 }
};
ConditionExpression condition2 = new ConditionExpression()
{
AttributeName = "returnedtypecode",
Operator = ConditionOperator.Equal,
Values = { Opportunity.EntityTypeCode }
};
FilterExpression filter = new FilterExpression();
filter.Conditions.Add(condition1);
filter.Conditions.Add(condition2);
QueryExpression queryToRetrieveViews = new QueryExpression
{
ColumnSet = new ColumnSet("savedqueryid", "name", "querytype", "isdefault", "returnedtypecode", "isquickfindquery"),
EntityName = SavedQuery.EntityLogicalName,
Criteria = filter
};
RetrieveMultipleRequest retrieveSavedViewsRequest = new RetrieveMultipleRequest { Query = queryToRetrieveViews };
RetrieveMultipleResponse retrieveSavedViewsResponse = (RetrieveMultipleResponse)crm.Execute(retrieveSavedViewsRequest);
DataCollection<Entity> savedViews = retrieveSavedViewsResponse.EntityCollection.Entities;
foreach (Entity ent in savedViews){...}
I did a quick watch but am unable to find the attribute that has the filter conditions as present in CRM. I mean what i intend to look at is something like this sayfor e.g. open opportunities the filter would be "statecode=0".
Is it possible to fetch the associated filters? -sorry by Associated filters i mean filters of the view
You can filter by whatever attribute you'd like so I'm not sure what you mean by the associated filters. If you mean the filter of the actual view you won't find it. Views are stored in XML, so you'll have to retrieve the the FetchXML for the saved view and parse the XML to see it's filter.

How to query multiple entities with a single QueryExpression

I am trying to run a microsoft dynamics crm 4.0 query. This works as expected when I generate a QueryExpression for "ONE" specific entity as I had done before. The issue however is how do i define more than one entity so i can apply logic that i have in another method? An example or illistration would be helpful.
so what i have is in this format:
static BusinessEntityCollection GetData(CrmService service)
{
cols = new ColumnSet();
cols.Attributes = new string[] { "x", "y", "z"};
FilterExpression filter = new FilterExpression();
filter.FilterOperator = LogicalOperator.And;
QueryExpression query = new QueryExpression();
query.EntityName = EntityName.incident.ToString();
// i am trying to add something like the below
query.EntityName = EntityName.account.toString();
query.ColumnSet = cols;
query.Criteria = filter;
return service.RetrieveMultiple(query);
}
The restriction I am facing is I can only query one entity and I need a solution or workaround to access and query multiple entities. Your help is much appreciated.
Simple answer: you can't. You could only query one entity at one time.
A query expression is used for single-object searches, for example, to search for all accounts that match certain search criteria.
See how to build queries.
You have to combine multiple requests for the entities you would like to get.
The same restriction exists for FetchXML. It is basically the serialized form of a QueryExpression. See how to use FetchXML

Categories