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.
Related
Please let me know how to save objects through relationship.
If I have two entities like Notes , Category entity
Note is one to one for Category.
Category Many to one for Notes.
How to save , if we have Category context to Notes..
Please provide me some inputs.
How to save through sets. It would be greatful
I have Employee and Department entities. Department has one to many relationship with Employee. Employee has one to one relationship with Department. I want save object of employee entity using department entity.
Each time I have create new Object for Employee –
import UIKit
import CoreData
class ViewController: UIViewController {
var container: NSPersistentContainer? = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer
let appDelegate = UIApplication.shared.delegate as! AppDelegate
var empSet = NSSet()
var empS = Set<EmployeeExample>()
override func viewDidLoad() {
super.viewDidLoad()
var context:NSManagedObjectContext = (container?.viewContext)!
let dept = NSEntityDescription.insertNewObject(forEntityName: "Department", into: context) as! Department
let emp = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: (container?.viewContext)!) as! Employee
emp.firstName = "YYYY"
emp.lastName = "HHHHHHH"
empS.insert(emp)
print("Count of Emp SSSS Set == \(empS.count)")
let emp1 = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: (container?.viewContext)!) as! Employee
emp1.firstName = "RRRRR"
emp1.lastName = "YYYYY"
empS.insert(emp1)
empSet.addingObjects(from: empS)
dept.deptName = "CCC"
print("Count of Emp SSSS Set == \(empS.count)")
print("Count of Emp Set == \(empSet.count)")
dept.addToEmp(empSet)
do {
try appDelegate.saveContext()
print("Saved -------------")
}catch {
print("Error")
}
}
}
I have doubt in these lines anEmployee.department = newDepartment How to get the newDepartment value. Whether i have to declare let newDepartment = NSEntityDescription.insertNewObject(forEntityName: "Department", into: (container?.viewContext)!) as! Department.
The Department object here is whatever object should be related to that specific Employee object. How you get it depends on how your app works, but you probably want to do one of these:
If the employee belongs to a new department that doesn't already exist in your app, you create a new instance of Department and assign that object as anEmployee.department.
If the employee belongs to a department that already exists in your app, you use an already existing Department. You probably get that by fetching Department objects from Core Data-- either with NSFetchRequest or by using an NSFetchedResultsController.
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
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.
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);
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.