MademoiselleLenore
MademoiselleLenore

Reputation: 569

Retrieving n to n records

(no, not the french girl again!!!)

So...I have two entities with a n-n relationship: "new_produit" and "new_lignecontrat". I need to copy the "new_produit" records of the last "new_lignecontrat" record into the newly created "new_lignecontrat".

The plugin is triggered on Create for new_lignecontrat.

So far, I've written this, but I'm not quite sure bout the steps to follow to copy "new_produit" records...

            else if (modeleContrat.Id.Equals (ContratForfaitaire))
            {

                FetchExpression fetch = new FetchExpression(@"
                    <fetch distinct='false' mapping='logical'>
                      <entity name='new_contrats'><link-entity name='" + context.PrimaryEntityName + "' alias='nombreligne' from='new_contratsid' to='new_contratsid'><filter type='and'><condition attribute='new_contratsid' value='" + contrats.Id + "' operator='eq'></condition></filter></link-entity></entity></fetch>");
                EntityCollection lines = service.RetrieveMultiple(fetch);

                if (lines.Entities.Any())
                {
                    var last = lines.Entities.Last();

                    if (last.GetAttributeValue<OptionSetValue>("statecode").Value == 1)
                    {

                        QueryExpression query = new QueryExpression();
                        query.EntityName = "new_produit";
                        query.ColumnSet = new ColumnSet("new_produitid");
                        Relationship relationship = new Relationship();

                        // name of relationship between team & systemuser
                        relationship.SchemaName = "new_new_lignecontrat_new_produit";
                        RelationshipQueryCollection relatedEntity = new RelationshipQueryCollection();
                        relatedEntity.Add(relationship, query);
                        RetrieveRequest request = new RetrieveRequest();
                        request.RelatedEntitiesQuery = relatedEntity;
                        request.ColumnSet = new ColumnSet("new_lignecontratid");
                        request.Target = new EntityReference
                        {
                            Id = last.Id,
                            LogicalName = last.LogicalName

                        };

                        RetrieveResponse response = (RetrieveResponse)service.Execute(request);



                        if (((DataCollection<Relationship, EntityCollection>)(((RelatedEntityCollection)(response.Entity.RelatedEntities)))).Contains(new Relationship("new_new_lignecontrat_new_produit")) && ((DataCollection<Relationship, EntityCollection>)(((RelatedEntityCollection)(response.Entity.RelatedEntities))))[new Relationship("new_new_lignecontrat_new_produit")].Entities.Count > 0)
                        {
                            response.Entity.Attributes.Remove("new_produitid");
                            response["new_lignecontratid"] = new EntityReference(target.LogicalName, target.Id);

Upvotes: 1

Views: 3815

Answers (1)

Peter Majeed
Peter Majeed

Reputation: 5352

I believe I answered this question partially in response to one of your previous questions, so let's see if my answer this time is any better.

The three steps in this problem, if I understand the problem correctly, is to first get the last new_lignecontrat record created before the create of the current new_lignecontrat record, then get all the new_produit records associated with the last new_lignecontrat, and finally Associate each of those new_produit records with the new new_lignecontrat record.

  1. For this query, you can use any of the three supported query methods in Dynamics (FetchXml, QueryExpression, and Linq). I prefer Linq as the .First() method is an easy way to execute an efficient TOP query (to get your last created new_lignecontrat record), but you can also use FetchXml and the paging cookie to accomplish the same (not sure about QueryExpression).

  2. You can get the linked new_produit records using the N:N table and the ID retrieved in step 1.

  3. Once you have the id of the new new_lignecontrat and the ids of the lastly associated new_produit records, execute the Associate method of your IOrganizationService against these records and their relationship. Below is a mockup that handles these three steps.

using (OrganizationServiceContext osc = new OrganizationServiceContext(service))
{
    //assumes early binding, but this can be modified for late binding as well
    Guid ligneContratID = (from lc in osc.CreateQuery<new_ligneContrat>()
                           where lc.CreatedOn < (DateTime)targetEntity.Attributes["CreatedOn"] //look at all new_ligneContrat records created before the newly created record
                           orderby lc.CreatedOn descending //sort newest to oldest
                           select lc.new_ligneContratID)
                           .First(); //get the newest record

    var produits = from lcp in osc.CreateQuery<new_new_lignecontrat_new_produit>()  //use your N:N relationship/table as your linking table
                   join p in osc.CreateQuery<new_produit>() on lcp.new_produitId equals p.new_produitId
                   where lcp.new_lignecontratId = ligneContratID //use the previous query result in your N:N lookup
                   select p.new_produitId;                        

    EntityReferenceCollection erc = new EntityReferenceCollection();
    foreach (var e in produits)
    {
        erc.Add(new EntityReference("new_produit", e));
    }

    service.Associate("new_lignecontrat", targetEntity.Id, new Relationship("new_new_lignecontrat_new_produit", erc);
}

Upvotes: 3

Related Questions