Retrieve N:N Relationship in Dynamics Crm - dynamics-crm-2011

Currency entity is associated N:N Relationship with Lead.Now I'm trying to Retrieve associated Currency with the lead.i'm getting problem transaction currency does'nt contain attribute with leadid.could any references plz...
if (context.InputParameters.Contains("Target") && (context.InputParameters["Target"]) is Entity)
{
Entity en = (Entity)context.InputParameters["Target"];
QueryExpression _Query = new QueryExpression
{
EntityName = "transactioncurrency",
ColumnSet = new ColumnSet(true),
LinkEntities =
{
new LinkEntity
{
Columns=new ColumnSet(true),
LinkFromEntityName="lead",
LinkFromAttributeName="leadid",
LinkToEntityName="new_lead_transactioncurrency",
LinkToAttributeName="transactioncurrencyid",
LinkCriteria=new FilterExpression
{
FilterOperator=LogicalOperator.And,
Conditions=
{
new ConditionExpression
{
AttributeName="transactioncurrencyid",
Operator=ConditionOperator.Equal,
Values={ en.Id }
}
}
}
}
}
};
EntityCollection entitycollect = service.RetrieveMultiple(_Query);
int entitycount = entitycollect.Entities.Count;
}

I think you need to identify the correct LinkFromAttributeName and LinkToAttributeName.
QueryExpression query = new QueryExpression(entity1);
query.ColumnSet = new ColumnSet(true);
LinkEntity linkEntity1 = new LinkEntity("lead", "new_lead_transactioncurrency", "leadid", "leadid", JoinOperator.Inner);
LinkEntity linkEntity2 = new LinkEntity("new_lead_transactioncurrency", "transactioncurrency", "transactioncurrencyid", "transactioncurrencyid", JoinOperator.Inner);
linkEntity1.LinkEntities.Add(linkEntity2);
query.LinkEntities.Add(linkEntity1);
// Add condition to match the Bike name with “Honda”
linkEntity2.LinkCriteria = new FilterExpression();
linkEntity2.LinkCriteria.AddCondition(new ConditionExpression("raj_bikename", ConditionOperator.Equal, "Honda"));
EntityCollection collRecords = service.RetrieveMultiple(query);
For reference please have a look at the followng links:
Retrieve associated records (N:N related)
Sample: Convert queries between Fetch and QueryExpression

Related

How to Add an optionset filter criteria in MS CRM Query Expression?

I have an entity LeaveType with two attributes, 1. Type, 2. Available Days, where Type is an optionset and Available days is a text field. I want to fetch all such LeaveType records where the Type = 'Annual' selected in the optionset. I am not able to find how to add a filter the query expression for the option set value. Below is my in progress method:
public Entity Getleavetype(Guid LeaveDetailsId, IOrganizationService _orgService, CodeActivityContext Acontext)
{
QueryExpression GetLeavedetails = new QueryExpression();
GetLeavedetails.EntityName = "sgfdhr_leavetype";
GetLeavedetails.ColumnSet = new ColumnSet("new_type");
GetLeavedetails.ColumnSet = new ColumnSet("new_availabledays");
GetLeavedetails.Criteria.AddCondition("new_type", ConditionOperator.Equal, "Annual" ); //Is this correct????
GetLeavedetails.Criteria.AddCondition("new_employeeleavecalculation", ConditionOperator.Equal, LeaveDetailsId); //ignore this
//((OptionSetValue)LeaveDetailsId["new_leavetype"]).Value
EntityCollection LeaveDetails = _orgService.RetrieveMultiple(GetLeavedetails);
return LeaveDetails[0];
}
In your condition you need to set the integer value of the optionset, not the label.
Assuming that Annual value is for example 2, the code will be:
GetLeavedetails.Criteria.AddCondition("new_type", ConditionOperator.Equal, 2);
You should use RetrieveAttributeRequest to find an int value of OptionSet text.
In my code it looks like:
private static int findParkedOptionValue(IOrganizationService service)
{
RetrieveAttributeRequest attributeRequest = new RetrieveAttributeRequest
{
EntityLogicalName = Model.Invite.ENTITY_NAME,
LogicalName = Model.Invite.COLUMN_STATUS,
RetrieveAsIfPublished = false
};
// Execute the request
RetrieveAttributeResponse attributeResponse =
(RetrieveAttributeResponse)service.Execute(attributeRequest);
var attributeMetadata = (EnumAttributeMetadata)attributeResponse.AttributeMetadata;
// Get the current options list for the retrieved attribute.
var optionList = (from o in attributeMetadata.OptionSet.Options
select new { Value = o.Value, Text = o.Label.UserLocalizedLabel.Label }).ToList();
int value = (int)optionList.Where(o => o.Text == "Парковка")
.Select(o => o.Value)
.FirstOrDefault();
return value;
}
In https://community.dynamics.com/enterprise/b/crmmemories/archive/2017/04/20/retrieve-option-set-metadata-in-c you found a perfect example.

Trying to query with OR on some related entities and AND on other related entities

I'm having some difficulty creating a query where I'm using Or on some related entity fields and And on some other related entity fields. I'm using QueryExpression since that is what I am most familiar with, but if there is a better way to do it, I'm all for it.
Specifically, I'm querying Contracts where either the BillTo.Name or the Customer.Name equal a passed in value, and some custom values on the associated Contract Line are equal to passed in values. This is what I have tried so far. The problem is that it is treating the BillTo name and Customer name with an And operator instead of an Or.
QueryExpression qe = new QueryExpression(Contract.EntityLogicalName);
ColumnSet acctColumns = new ColumnSet("name");
LinkEntity acctlink = new LinkEntity("contract", "account", "customerid", "accountid", JoinOperator.Inner);
acctlink.LinkCriteria.FilterOperator = LogicalOperator.Or;
acctlink.LinkCriteria.AddCondition("name", ConditionOperator.Equal, CustName);
acctlink.Columns = acctColumns;
qe.LinkEntities.Add(acctlink);
ColumnSet billToColumns = new ColumnSet("name");
LinkEntity billToLink = new LinkEntity("contract", "account", "billingcustomerid", "accountid", JoinOperator.Inner);
billToLink.LinkCriteria.FilterOperator = LogicalOperator.Or;
billToLink.LinkCriteria.AddCondition("name", ConditionOperator.Equal, CustName);
billToLink.Columns = billToColumns;
qe.LinkEntities.Add(billToLink);
ColumnSet contractColumns = new ColumnSet("expireson");
LinkEntity contractLineLink = new LinkEntity("contract", "contractdetail", "contractid", "contractid", JoinOperator.Inner);
contractLineLink.Columns = contractColumns;
LinkEntity productLink = new LinkEntity("contractdetail", "product", "productid", "productid", JoinOperator.Inner);
productLink.LinkCriteria.AddCondition("productnumber", ConditionOperator.Equal, ProductID);
contractLineLink.LinkEntities.Add(productLink);
qe.LinkEntities.Add(contractLineLink);
FilterExpression fe = new FilterExpression(LogicalOperator.And);
ConditionExpression ceVersion = new ConditionExpression("new_version", ConditionOperator.Equal, versionID);
ConditionExpression ceCust = new ConditionExpression("new_cust", ConditionOperator.Equal, true);
ConditionExpression ceComp = new ConditionExpression("new_comp", ConditionOperator.Like, formattedDBName);
fe.AddCondition(ceVersion);
fe.AddCondition(ceCust);
fe.AddCondition(ceComp);
qe.Criteria.AddFilter(fe);
qe.ColumnSet = cs;
EntityCollection contractDetails = crmService.RetrieveMultiple(qe);
EDIT - Final code
Here's what I ended up doing after reading through the options that Darin mentioned.
Guid acctGuid = acctRef.Id; // Retrieve EntityReference in another method
ColumnSet cs = new ColumnSet();
QueryExpression qe = new QueryExpression(Contract.EntityLogicalName);
ColumnSet contractColumns = new ColumnSet("expireson", "new_registrationkey");
LinkEntity contractLineLink = new LinkEntity("contract", "contractdetail", "contractid", "contractid", JoinOperator.Inner);
contractLineLink.Columns = contractColumns;
LinkEntity productLink = new LinkEntity("contractdetail", "product", "productid", "productid", JoinOperator.Inner);
productLink.LinkCriteria.AddCondition("productnumber", ConditionOperator.Equal, ProductID);
contractLineLink.LinkEntities.Add(productLink);
qe.LinkEntities.Add(contractLineLink);
FilterExpression fe = new FilterExpression(LogicalOperator.And);
ConditionExpression ceVersion = new ConditionExpression("new_version", ConditionOperator.Equal, VersionID);
ConditionExpression ceCust = new ConditionExpression("new_cust", ConditionOperator.Equal, true);
ConditionExpression ceComp = new ConditionExpression("new_comp", ConditionOperator.Like, formattedName);
fe.AddCondition(ceVersion);
fe.AddCondition(ceCust);
fe.AddCondition(ceComp);
qe.Criteria.AddFilter(fe);
qe.ColumnSet = cs;
FilterExpression fe2 = new FilterExpression(LogicalOperator.Or);
ConditionExpression ceCustomerName = new ConditionExpression("customerid", ConditionOperator.Equal, acctGuid);
ConditionExpression ceBillToName = new ConditionExpression("billingcustomerid", ConditionOperator.Equal, acctGuid);
fe2.AddCondition(ceCustomerName);
fe2.AddCondition(ceBillToName);
qe.Criteria.AddFilter(fe2);
EntityCollection contractDetails = crmService.RetrieveMultiple(qe);
You've got two options
Change your InnerJoin's to LeftOuter's, then filter the results on the client side.
Perform two separate queries, one with an inner join for the customer id, and one for an inner join for the billing customer id, then combine them on the client side.
The FilterOperator = LogicalOperator.Or only works on ConditionExpressions within the Filter, and since you're only setting one ConditionExpression it doesn't really do anything.

Get entities by multiple ids in N:N relation

Given entities:
Team, User. Relation between those is N:N.
Question:
How do I find users which belong to specified teams (with given list of ids).
PS.
I found how to do with single team, but have no clue how to deal with the list of teams?
var team_id = ...
QueryExpression query = new QueryExpression("user");
// setting up relation between teams and users
Relationship rel = new Relationship();
rel.SchemaName = "new_teams_users";
RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();
relatedEntity.Add(rel, query);
RetrieveRequest request = new RetrieveRequest();
request.RelatedEntitiesQuery = relatedEntity;
request.ColumnSet = new ColumnSet(new string[] {"id"});
request.Target = new EntityReference { Id = team_id, LogicalName = "new_team" };
// Results: List of users by team id.
RetrieveResponse response = (RetrieveResponse)CrmService.Execute(request);
QueryExpression build on intersect entity will help you. As example i used product and competitor N:N relationship
QueryExpression qe = new QueryExpression()
{
EntityName = "competitorproduct", //this name can be get from N:N rel properties (Relationship form, Relationship Entity Name field)
ColumnSet = new ColumnSet(true),
};
qe.Criteria.AddCondition(
"competitorid",
ConditionOperator.In,
new object[] { "GUID1", "GUID2"});
//Below is optional - if you need some details of entity, add LinkEntity object. This example adds all fields from product entity
LinkEntity lePorduct = new LinkEntity("competitorproduct", "product", "productid", "productid", JoinOperator.Inner);
lePorduct.Columns = new ColumnSet(true);
qe.LinkEntities.Add(lePorduct);
You would make your primary entity the intersection entity so in your example it would be "TeamMembership" the criteria would then be set against the attribute "SystemUserId".
To get more information on the team you need to add the team entity as a linked entity to your query like this
LinkEntity TeamLink = new LinkEntity();
TeamLink .EntityAlias = "TeamLink ";
TeamLink .JoinOperator = JoinOperator.Inner;
TeamLink .LinkFromEntityName = "teammembership";
TeamLink .LinkFromAttributeName = "teamid";
TeamLink .LinkToEntityName = "team";
TeamLink .LinkToAttributeName = "teamid";
You can then bring back what ever columns you want and get the data out.

MS Dynamics: How to remove all association of the Entity

I have an appointment entity which has an association with contact entity. I am trying to remove all association from this appointment entity without explicitly providing contact_id. Here is my code snippet with create appointment entity and then associate with an existing contact.
Entity activity = new Entity("appointment");
activity["scheduledstart"] = DateTime.Now;
activity["scheduledend"] = DateTime.Now.AddMinutes(30);
activity["subject"] = "Test Meeting";
activity["description"] = "Test Description";
activity["owneridname"] = "test_user";
activity["location"] = "Dallas";
EntityCollection attendees = new EntityCollection();
Entity attendee1 = new Entity("activityparty");
attendee1["addressused"] = "test.test#acmegroup.com";
attendees.Entities.Add(attendee1);
activity["requiredattendees"] = attendees;
Guid id = _service.Create(activity);
Console.WriteLine("id: " + id);
AssociateRequest associateRequest = new AssociateRequest();
associateRequest.Relationship = new Relationship("new_appointment_contact");
associateRequest.Target = new Microsoft.Xrm.Sdk.EntityReference("appointment", id);
EntityReferenceCollection referenceCollection = new EntityReferenceCollection();
Microsoft.Xrm.Sdk.EntityReference entityReference = new Microsoft.Xrm.Sdk.EntityReference("contact", new Guid("e6e71e53-b44b-e211-a81e-0050568b36bf"));
referenceCollection.Add(entityReference);
associateRequest.RelatedEntities = referenceCollection;
// Execute the request.
_service.Execute(associateRequest);
I am aware of using DisassociateRequest to remove this association but I don't want to explicitly provide contact_id. I just need something like .Clear() which can
remove all contact association.
DisassociateRequest disassociateRequest = new DisassociateRequest();
disassociateRequest.Relationship = new Relationship("new_appointment_contact");
disassociateRequest.Target = new Microsoft.Xrm.Sdk.EntityReference("appointment", id);
EntityReferenceCollection referenceCollection2 = new EntityReferenceCollection();
Microsoft.Xrm.Sdk.EntityReference entityReference2 = new Microsoft.Xrm.Sdk.EntityReference("contact", new Guid("e6e71e53-b44b-e211-a81e-0050568b36bf"));
referenceCollection2.Add(entityReference2);
disassociateRequest.RelatedEntities = referenceCollection2;
// Execute the request.
_service.Execute(disassociateRequest);
I used GetRelatedEntities method to pull all related entities into collection and then use this collection to disassociate all related entities:
DisassociateRequest disassociateRequest = new DisassociateRequest();
disassociateRequest.Relationship = new Relationship("new_appointment_contact");
disassociateRequest.Target = new Microsoft.Xrm.Sdk.EntityReference("appointment", id);
EntityReferenceCollection referenceCollection2 = new EntityReferenceCollection();
Entity existingAppointment = _service.Retrieve("appointment", id, new ColumnSet(true));
foreach (Entity item in existingAppointment.GetRelatedEntities(orgContext, "new_appointment_contact"))
{
Guid contactId = new Guid(item["contactid"].ToString());
Microsoft.Xrm.Sdk.EntityReference entityReference2 = new Microsoft.Xrm.Sdk.EntityReference("contact", contactId);
referenceCollection2.Add(entityReference2);
}
disassociateRequest.RelatedEntities = referenceCollection2;
_service.Execute(disassociateRequest);

How to obtain members of a marketing list using QueryExpression object?

I'm using QueryExpression often but this far, it's been a straigh-forward get-this-from-that or put-this-in-that. Recently, I learned that there's something called LinkedEntity and I started looking for it. As an example I got inspired by a related question here on SO and I started to create an expression for getting all the members of a list given it's guid.
All the examples I've found follow the same pattern, though - as this example illustrates. From this question, I've learned that it's an obsolete approach (CRM 4.0). I've failed founding a more up-to-date example and I'm not sure how to design the linkage.
Anybody cares to provide a sample code?
Guid guid = ...;
QueryExpression request = new QueryExpression
{
EntityName = "account",
ColumnSet = new ColumnSet(true),
LinkEntities= ???, // How to link the entities correctly?
Criteria = new FilterExpression { ??? } // How to filter for *guid* only?
};
I've created a fetch-XML linking two entities but I'm not clear on how to translate it to QueryExpression entity. I've got something like this. Any suggestions?
LinkEntity linkListToMember = new LinkEntity(
"list", "listmember", "listid", "listid", JoinOperator.Natural);
LinkEntity linkMemberToContact = new LinkEntity(
"listmember", "account", "entityid", "accountid", JoinOperator.Natural);
A Link Entity serves as your SQL Join. Use the Constructor with the from and to entity and attribute names
public LinkEntity(
string linkFromEntityName, // This is the Entity Logical Name of your Query Expression, or parent LinkEntity
string linkToEntityName, // This is the Entity Logical Name of the entity you'd like to link to
string linkFromAttributeName, // This is the attribute name on your from entity, containing your join key
string linkToAttributeName, // This is the attribute name on your to entity, containing your join key
JoinOperator joinOperator) // This is the type of Join you'd like to perform
Using the Link Entity, you can add Link Criteria to filter the results returned. You can also add Columns and return data from related entities.
Edit, an Addition to Konrad's Answer
If the 52 lines of code that Konrad lists seems too verbose, this will do the same exact thing, in 15 lines, using the extension methods defined here.
Guid guid = ...;
IOrganizationService service;
QueryExpression request = new QueryExpression("account")
{
ColumnSet = new ColumnSet("name", "region"),
};
request.Criteria.AddCondition("name", ConditionOperator.NotNull);
request.Criteria.AddCondition("region", ConditionOperator.NotNull);
var listLink = request.AddLink("listmember", "accountid", "entityid").
AddChildLink("list", "listid");
listLink.Columns.AddColumn("listname");
listLink.LinkCriteria.AddCondition("listid", ConditionOperator.Equal, guid);
Here's a method for getting all the members of a marketing list, given that you have its guid and a server connection. What you did with the conditions is right spot on but you need to jack the one into the other. On Saturday I'll put it with a larger description on my blog.
Guid guid = ...;
IOrganizationService service;
QueryExpression request = new QueryExpression
{
EntityName = "account",
ColumnSet = new ColumnSet("name", "region"),
LinkEntities =
{
new LinkEntity
{
JoinOperator = JoinOperator.Inner,
LinkFromEntityName = "account",
LinkFromAttributeName = "accountid",
LinkToEntityName = "listmember",
LinkToAttributeName = "entityid",
LinkCriteria = { },
LinkEntities =
{
new LinkEntity
{
JoinOperator = JoinOperator.Inner,
Columns = new ColumnSet("listname"),
EntityAlias = "MarketingList",
LinkFromEntityName = "listmember",
LinkFromAttributeName = "listid",
LinkToEntityName = "list",
LinkToAttributeName = "listid",
LinkCriteria = { Conditions =
{
new ConditionExpression("listid", ConditionOperator.Equal, guid)
} }
}
}
}
},
Criteria = new FilterExpression
{
Filters =
{
new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression("name", ConditionOperator.NotNull),
new ConditionExpression("region", ConditionOperator.NotNull)
}
}
}
}
};
Then, of course you need to execute the call.
EntityCollection result = service.RetrieveMultiple(request);
Finally, you might want to order and structure whatever you've got from the server. I'm using the following LINQ-to-Data expression.
IEnumerable<Member> output = result.Entities.Where(element
=> Member.IsWellFormed(element)).Select(element
=> new Member(element));
More on the subject, see the blog.

Resources