Insert or update a record using Upsert

This sample code shows how to insert or update records by using the Upsert message introduced with Microsoft Dynamics CRM Online 2015 Update 1.

C# (643.4 KB)
 
 
 
 
 
(0)
1,059 times
Add to favorites
4/10/2015
E-mail Twitter del.icio.us Digg Facebook
// =====================================================================
//
//  This file is part of the Microsoft Dynamics CRM SDK code samples.
//
//  Copyright (C) Microsoft Corporation.  All rights reserved.
//
//  This source code is intended only as a supplement to Microsoft
//  Development Tools and/or on-line documentation.  See these other
//  materials for detailed information regarding Microsoft code samples.
//
//  THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//
// =====================================================================
//<snippetProductUpsertSample>
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Diagnostics;
using System.Xml.Linq;
using System.IO;
using System.Collections.Generic;
using System.Xml;
using System.Threading;

// These namespaces are found in the Microsoft.Xrm.Sdk.dll assembly
// found in the SDK\bin folder.
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Discovery;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Sdk.Metadata.Query;

// This namespace is found in Microsoft.Crm.Sdk.Proxy.dll assembly
// found in the SDK\bin folder.
using Microsoft.Crm.Sdk.Messages;

namespace Microsoft.Crm.Sdk.Samples
{
    public class ProductUpsertSample
    {
        #region Class Level Members
        /// <summary>
        /// Stores the organization service proxy.
        /// </summary>

        private OrganizationServiceProxy _serviceProxy;
        private const String _customProductsEntityName = "sample_product";
        System.String ManagedSolutionLocation = @".\\UpsertSample_1_0_0_0_managed.zip";

        #endregion Class Level Members

        #region How To Sample Code
        /// <summary>
        /// Imports the UpsertSample solution if it is not already installed.
        /// Inserts the new records from newsampleproduct.xml to sample_product entity using Upsert.
        /// Updates records in sample_product with data from updatedsampleproduct.xml using Upsert.
        /// Optionally allows the user view the records in browser.
        /// Optionally deletes the UpsertSsample solution.
        /// </summary>
        /// <param name="serverConfig">Contains server connection information.</param>
        /// <param name="promptForDelete">When True, the user will be prompted to delete all
        /// created entities.</param>
        public void Run(ServerConnection.Configuration serverConfig, bool promptForDelete)
        {
            try
            {
                // Connect to the Organization service. 
                // The using statement assures that the service proxy will be properly disposed.
                using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri, serverConfig.Credentials, serverConfig.DeviceCredentials))
                {

                    // This statement is required to enable early-bound type support.
                    _serviceProxy.EnableProxyTypes();

                    // Imports the UpsertSample solution if it is not already installed.
                    ImportUpsertSampleSolution();

                    // Waits for the alternate key to be active.
                    WaitForEntityAndKeysToBeActive(_serviceProxy, _customProductsEntityName.ToLower());

                    // Processes the data in newsampleproduct.xml 
                    // to represent new products. Creates 13 records in sample_product entity.
                    // RecordCreated property returns true to indicate the records were created.

                    ProcessUpsert(".\\newsampleproduct.xml");

                    // Processes the data in updatedsampleproduct.xml 
                    // to represent updates to products previously created. 
                    // Updates 6 existing records in sample_product entity.
                    // RecordCreated property returns false to indicate the existing records were updated.
                    ProcessUpsert(".\\updatedsampleproduct.xml");

                    // Prompts to delete the UpsertSample managed solution.
                    DeleteUpsertSampleSolution(promptForDelete);

                }
            }

            // Catch any service fault exceptions that Microsoft Dynamics CRM throws.
            catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>)
            {
                // You can handle an exception here or pass it back to the calling method.
                throw;
            }
        }

        /// <summary>
        /// Checks whether the UpsertSample solution is already installed.
        /// If it is not, the UpsertSample_1_0_0_0_managed.zip file is imported to install
        /// this solution.
        /// </summary>
        public void ImportUpsertSampleSolution()
        {
            try
            {

                Console.WriteLine("Checking whether the UpsertSample solution already exists.....");

                QueryByAttribute queryCheckForSampleSolution = new QueryByAttribute();
                queryCheckForSampleSolution.AddAttributeValue("uniquename", "UpsertSample");
                queryCheckForSampleSolution.EntityName = Solution.EntityLogicalName;

                EntityCollection querySampleSolutionResults = _serviceProxy.RetrieveMultiple(queryCheckForSampleSolution);
                Solution SampleSolutionResults = null;
                if (querySampleSolutionResults.Entities.Count > 0)
                {
                    Console.WriteLine("The {0} solution already exists....", "UpsertSample");
                    SampleSolutionResults = (Solution)querySampleSolutionResults.Entities[0];

                }
                else
                {
                    Console.WriteLine("The UpsertSample solution does not exist. Importing the solution....");
                    byte[] fileBytes = File.ReadAllBytes(ManagedSolutionLocation);
                    ImportSolutionRequest impSolReq = new ImportSolutionRequest()
                    {
                        CustomizationFile = fileBytes
                    };

                    _serviceProxy.Execute(impSolReq);

                    Console.WriteLine("Imported Solution from {0}", ManagedSolutionLocation);

                }
            }

             // Catch any service fault exceptions that Microsoft Dynamics CRM throws.
            catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>)
            {
                // You can handle an exception here or pass it back to the calling method.
                throw;
            }
        }

        //<snippetProductUpsertSample1>
        public void ProcessUpsert(String Filename)
        {
            Console.WriteLine("Executing upsert operation.....");
            XmlTextReader tr = new XmlTextReader(Filename);
            XmlDocument xdoc = new XmlDocument();
            xdoc.Load(tr);
            XmlNodeList xnlNodes = xdoc.DocumentElement.SelectNodes("/products/product");

            foreach (XmlNode xndNode in xnlNodes)
            {
                String productCode = xndNode.SelectSingleNode("Code").InnerText;
                String productName = xndNode.SelectSingleNode("Name").InnerText;
                String productCategory = xndNode.SelectSingleNode("Category").InnerText;
                String productMake = xndNode.SelectSingleNode("Make").InnerText;

                //use alternate key for product
                Entity productToCreate = new Entity("sample_product", "sample_productcode", productCode);

                productToCreate["sample_name"] = productName;
                productToCreate["sample_category"] = productCategory;
                productToCreate["sample_make"] = productMake;
                UpsertRequest request = new UpsertRequest()
                {
                    Target = productToCreate
                };

                try
                {
                    // Execute UpsertRequest and obtain UpsertResponse. 
                    UpsertResponse response = (UpsertResponse)_serviceProxy.Execute(request);
                    if (response.RecordCreated)
                        Console.WriteLine("New record {0} is created!", productName);
                    else
                        Console.WriteLine("Existing record {0} is updated!", productName);
                }

                // Catch any service fault exceptions that Microsoft Dynamics CRM throws.
                catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>)
                {
                    throw;
                }

            }
            // Prompts to view the sample_product entity records.
            // If you choose "y", IE will be launched to display the new or updated records.
            if (PromptForView())
            {
                ViewEntityListInBrowser();
            }

        }
        //</snippetProductUpsertSample1>
        /// <summary>
        /// Deletes the managed solution that was created for this sample.
        /// <param name="prompt"> Indicates whether to prompt the user to delete 
        /// the solution created in this sample.</param>
        /// If you choose "y", the managed solution will be deleted including the 
        /// sample_product entity and all the data in the entity. 
        /// If you choose "n", you must delete the solution manually to return 
        /// your organization to the original state.
        /// </summary>
        public void DeleteUpsertSampleSolution(bool prompt)
        {
            bool deleteSolution = true;
            if (prompt)
            {
                Console.WriteLine("\nDo you want to delete the Upsert Sample solution? (y/n)");
                String answer = Console.ReadLine();

                deleteSolution = (answer.StartsWith("y") || answer.StartsWith("Y"));
            }
            if (deleteSolution)
            {
                Console.WriteLine("Deleting the {0} solution....", "Upsert Sample");
                QueryExpression queryImportedSolution = new QueryExpression
                {
                    EntityName = Solution.EntityLogicalName,
                    ColumnSet = new ColumnSet(new string[] { "solutionid", "friendlyname" }),
                    Criteria = new FilterExpression()
                };
                queryImportedSolution.Criteria.AddCondition("uniquename", ConditionOperator.Equal, "UpsertSample");

                Solution ImportedSolution = (Solution)_serviceProxy.RetrieveMultiple(queryImportedSolution).Entities[0];

                _serviceProxy.Delete(Solution.EntityLogicalName, (Guid)ImportedSolution.SolutionId);

                Console.WriteLine("Deleted the {0} solution.", ImportedSolution.FriendlyName);
            }


        }


        // Prompt to view the entity.
        private static bool PromptForView()
        {
            Console.WriteLine("\nDo you want to view the sample product entity records? (y/n)");
            String answer = Console.ReadLine();
            if (answer.StartsWith("y") || answer.StartsWith("Y"))
            { return true; }
            else
            { return false; }
        }

        /// <summary>
        /// Alternate keys may not be active immediately after the UpsertSample 
        /// solution is installed.This method polls the metadata for the sample_product
        /// entity to delay execution of the rest of the sample until the alternate keys are ready.
        /// </summary>
        /// <param name="service">Specifies the service to connect to.</param>
        /// <param name="entityLogicalName">The entity logical name, i.e. sample_product.</param>
        private static void WaitForEntityAndKeysToBeActive(IOrganizationService service, string entityLogicalName)
        {
            EntityQueryExpression entityQuery = new EntityQueryExpression();
            entityQuery.Criteria = new MetadataFilterExpression(LogicalOperator.And)
            {
                Conditions = { { new MetadataConditionExpression("LogicalName", MetadataConditionOperator.Equals, entityLogicalName) } }
            };

            entityQuery.Properties = new MetadataPropertiesExpression("Keys");

            RetrieveMetadataChangesRequest metadataRequest = new RetrieveMetadataChangesRequest() { Query = entityQuery };

            bool allKeysReady = false;
            do
            {
                System.Threading.Thread.Sleep(5000);

                Console.WriteLine("Check for Entity...");
                RetrieveMetadataChangesResponse metadataResponse = (RetrieveMetadataChangesResponse)service.Execute(metadataRequest);

                if (metadataResponse.EntityMetadata.Count > 0)
                {
                    EntityKeyMetadata[] keys = metadataResponse.EntityMetadata[0].Keys;

                    allKeysReady = true;
                    if (keys.Length == 0)
                    {
                        Console.WriteLine("No Keys Found!!!");
                        allKeysReady = false;
                    }
                    else
                    {
                        foreach (var key in keys)
                        {
                            Console.WriteLine("  Key {0} status {1}", key.SchemaName, key.EntityKeyIndexStatus);
                            allKeysReady = allKeysReady && (key.EntityKeyIndexStatus == EntityKeyIndexStatus.Active);
                        }
                    }

                }
            } while (!allKeysReady);

            Console.WriteLine("Waiting 30 seconds for metadata caches to all synchronize...");
            System.Threading.Thread.Sleep(TimeSpan.FromSeconds(30));
        }

        // Displays the sample product entity records in the browser.
        public void ViewEntityListInBrowser()
        {

            try
            {
                // Get the view ID
                QueryByAttribute query = new QueryByAttribute("savedquery");
                query.AddAttributeValue("returnedtypecode", "sample_product");
                query.AddAttributeValue("name", "Active Sample Products");
                query.ColumnSet = new ColumnSet("savedqueryid", "name");
                query.AddOrder("name", OrderType.Ascending);
                RetrieveMultipleRequest req = new RetrieveMultipleRequest() { Query = query };
                RetrieveMultipleResponse resp = (RetrieveMultipleResponse)_serviceProxy.Execute(req);

                SavedQuery activeSampleProductsView = (SavedQuery)resp.EntityCollection[0];

                String webServiceURL = _serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Address.Uri.AbsoluteUri;
                String entityInDefaultSolutionUrl = webServiceURL.Replace("XRMServices/2011/Organization.svc",
                String.Format("main.aspx?etn={0}&pagetype=entitylist&viewid=%7b{1}%7d&viewtype=1039", "sample_product", activeSampleProductsView.SavedQueryId));

                // View in IE
                ProcessStartInfo browserProcess = new ProcessStartInfo("iexplore.exe");
                browserProcess.Arguments = entityInDefaultSolutionUrl;
                Process.Start(browserProcess);

            }
            catch (SystemException)
            {
                Console.WriteLine("\nThere was a problem opening Internet Explorer.");
            }


        }
        #endregion How To Sample Code*

        #region Main
        /// <summary>
        /// Standard Main() method used by most SDK samples.
        /// </summary>
        /// <param name="args"></param>
        static public void Main(string[] args)
        {
            try
            {
                // Obtain the target organization's Web address and client logon 
                // credentials from the user.
                ServerConnection serverConnect = new ServerConnection();
                ServerConnection.Configuration config = serverConnect.GetServerConfiguration();

                ProductUpsertSample app = new ProductUpsertSample();
                app.Run(config, true);
            }
            catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> ex)
            {
                Console.WriteLine("The application terminated with an error.");
                Console.WriteLine("Timestamp: {0}", ex.Detail.Timestamp);
                Console.WriteLine("Code: {0}", ex.Detail.ErrorCode);
                Console.WriteLine("Message: {0}", ex.Detail.Message);
                Console.WriteLine("Plugin Trace: {0}", ex.Detail.TraceText);
                Console.WriteLine("Inner Fault: {0}",
                    null == ex.Detail.InnerFault ? "No Inner Fault" : "Has Inner Fault");
            }
            catch (System.TimeoutException ex)
            {
                Console.WriteLine("The application terminated with an error.");
                Console.WriteLine("Message: {0}", ex.Message);
                Console.WriteLine("Stack Trace: {0}", ex.StackTrace);
                Console.WriteLine("Inner Fault: {0}",
                    null == ex.InnerException.Message ? "No Inner Fault" : ex.InnerException.Message);
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("The application terminated with an error.");
                Console.WriteLine(ex.Message);

                // Display the details of the inner exception.
                if (ex.InnerException != null)
                {
                    Console.WriteLine(ex.InnerException.Message);

                    FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> fe = ex.InnerException
                        as FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>;
                    if (fe != null)
                    {
                        Console.WriteLine("Timestamp: {0}", fe.Detail.Timestamp);
                        Console.WriteLine("Code: {0}", fe.Detail.ErrorCode);
                        Console.WriteLine("Message: {0}", fe.Detail.Message);
                        Console.WriteLine("Plugin Trace: {0}", fe.Detail.TraceText);
                        Console.WriteLine("Inner Fault: {0}",
                            null == fe.Detail.InnerFault ? "No Inner Fault" : "Has Inner Fault");
                    }
                }
            }

            finally
            {

                Console.WriteLine("Press <Enter> to exit.");
                Console.ReadLine();
            }

        }
        #endregion Main

    }
}
//</snippetProductUpsertSample>