Dynamics CRM 2011 の IOrganizationService を使用したLate Binding によるレコードの操作のサンプルを掲載します。使用できるメソッドやリクエストの種類の一覧については、下記リンクを参照してください。

Organization Service Methods
http://technet.microsoft.com/en-us/library/gg328198.aspx
xRM Messages in the Organization Service
http://technet.microsoft.com/en-us/library/gg334698.aspx
CRM Messages in the Organization Service
http://technet.microsoft.com/en-us/library/gg309482.aspx

OrganizationRequest を使用する場合は、重複レコードの登録・更新を行うかや、メタデータ操作時にソリューションを指定するなどオプションパラメータが指定できます。 詳細は下記のリンク参照

Use Messages (Request and Response Classes) with the Execute Method
http://technet.microsoft.com/en-us/library/gg328075.aspx

今回は、 OrganizationServiceProxy を使用して、レコードの簡単なCRUD操作のサンプルを掲載します。OrganizationRequest を継承した CRUD用のRequest クラスを使用した CRUD のサンプルも掲載します。

動作環境

  • Windows Server 2008 R2 上に構築したオールインワンのDynamics CRM 2011 UR 3
  • Visual Studio 2010 Professional

1. プロジェクトのセットアップ

Visual Studio を起動し、コンソール用のプロジェクトを新規作成します。必要なdllの参照設定は、[Dynamics CRM 2011]遅延バインディング(Late Binding) でCRM Webサービス に接続するを参照してください。

2.IOrganizationServiceを使用したレコードのCRUDサンプルプログラム

IOrganizationServiceの Retrieve, Create, Delete, RetrieveMultiple, Update メソッドを使用したサンプル(CRUDContactメソッド)とOrganizationRequest を使用したサンプル(CRUDContactWithOrganizationRequest) を掲載します。サンプルでは所属企業の上司にハードコードでGUIDを設定しているので、サンプルを動作させる場合は、コメントにするが、環境に実在するレコードのGUIDを設定してください。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk;
using System.ServiceModel;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;

namespace LateBindingSample04
{
    class Program
    {
        static void Main(string[] args)
        {
            using (OrganizationServiceProxy service = GetOrganizationService("crmsvr01", "org01"))
            {
                try
                {
                    // コンタクトの操作
                    CRUDContact(service);
                    //CRUDContactWithOrganizationRequest(service);
                }
                catch (TimeoutException)
                {
                    Console.WriteLine("Timeout");
                }
                catch (FaultException<OrganizationServiceFault> fe)
                {
                    Console.WriteLine("FaultException<OrganizationServiceFault>");
                    Console.WriteLine(fe.Detail.Message);
                }
                catch (FaultException)
                {
                    Console.WriteLine("FaultException");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception");
                    Console.WriteLine(ex.Message);
                }
                Console.WriteLine("Press Enter to exit.");
                Console.ReadLine();
            }
        }

        /// <summary>
        /// contact エンティティを作ったり削除したり検索したり更新したり状態変更したり
        /// </summary>
        /// <param name="service"></param>
        public static void CRUDContact(IOrganizationService service)
        {
            // 取引先担当者の作成 Create
            Entity contact1 = new Entity("contact");
            // string
            contact1["firstname"] = "名1";
            contact1["lastname"] = "コンタクトの姓";
            // 通貨
            contact1["annualincome"] = new Money(10000000m);

            // OptionSet
            contact1["accountrolecode"] = new OptionSetValue(2); // 会社員

            Guid contact1id = service.Create(contact1);

            // 単一レコードを取得 Retrieve
            // 全フィールドを検索.実際には必要なフィールドのみ指定すること
            contact1 = service.Retrieve("contact", contact1id, new ColumnSet(true));

            // 更新 Update
            // 値がnullかのチェック。ContainsKeyなどでもチェックできそう
            if (contact1.GetAttributeValue<Money>("creditlimit") == null)
            {
                contact1.Attributes["creditlimit"] = new Money(2010);
            }
            if (contact1.GetAttributeValue<double?>("address1_latitude") == null)
            {
                // Do nothing
            }
            // 年収を更新
            contact1["annualincome"] = new Money(9999m);
            contact1.Attributes.Remove("annualincome"); // 更新取り消し
            contact1.Attributes["lastname"] = null; //null値で更新
            // customer(所属取引先企業/上司)の設定(Lookupも同じ)
            contact1.Attributes["parentcustomerid"] = new EntityReference("account", new Guid("F718680D-4BFA-E011-85FA-00155D0A0B14"));
            service.Update(contact1);

            contact1 = service.Retrieve("contact", contact1id, new ColumnSet(true));

            // 取引先担当者の非アクティブ化 Execute (SetStateRequest)
            contact1 = new Entity("contact");
            SetStateRequest setstateRequest = new SetStateRequest();
            setstateRequest.EntityMoniker = new EntityReference("contact", contact1id);
            setstateRequest.State = new OptionSetValue(1);
            setstateRequest.Status = new OptionSetValue(-1); // 既定のステータス
            service.Execute(setstateRequest);

            // 複数レコード検索 RetrieveMultiple
            // QueryExpression や FetchExpressionでレコードを検索
            QueryExpression query = new QueryExpression("contact");
            query.Criteria.Filters.Add(new FilterExpression()
            {
                FilterOperator = LogicalOperator.And,
                Conditions =
                {
                    new ConditionExpression("firstname", ConditionOperator.Equal, "名1")
                }
            });
            query.ColumnSet = new ColumnSet("firstname", "lastname");
            EntityCollection results =  service.RetrieveMultiple(query);
            foreach (var result in results.Entities)
            {
                Console.WriteLine("{0} {1}", result.GetAttributeValue<string>("firstname"), result.GetAttributeValue<string>("lastname"));
            }
            
            // 取引先担当者の削除 Delete
            service.Delete("contact", contact1id);

            // NN関連を設定する場合は Associate, Disassociate を使用する
        }

        /// <summary>
        /// OrganizationRequest を使用して、contact エンティティを作ったり
        /// 削除したり検索したり更新したり状態変更したり
        /// </summary>
        /// <param name="service"></param>
        public static void CRUDContactWithOrganizationRequest(IOrganizationService service)
        {
            // 取引先担当者の作成 CreateRequest
            Entity contact1 = new Entity("contact");
            // string
            contact1["firstname"] = "名2";
            contact1["lastname"] = "コンタクトの姓";
            // 通貨
            contact1["annualincome"] = new Money(10000000m);

            // OptionSet
            contact1["accountrolecode"] = new OptionSetValue(2); // 会社員
            CreateRequest createRequest = new CreateRequest()
            {
                Target = contact1
            };
            CreateResponse createResponse = service.Execute(createRequest) as CreateResponse;
            Guid contact1id = createResponse.id;

            // 単一レコードを取得 Retrieve
            // 全フィールドを検索.実際には必要なフィールドのみ指定すること
            RetrieveRequest retrieveRequest = new RetrieveRequest()
            {
                Target = new EntityReference("contact", contact1id),
                ColumnSet = new ColumnSet(true)
            };
            RetrieveResponse retrieveResponse = service.Execute(retrieveRequest) as RetrieveResponse;
            contact1 = retrieveResponse.Entity;

            // 更新 Update
            // 値がnullかのチェック。ContainsKeyなどでもチェックできそう
            if (contact1.GetAttributeValue<Money>("creditlimit") == null)
            {
                contact1.Attributes["creditlimit"] = new Money(2010);
            }
            if (contact1.GetAttributeValue<double?>("address1_latitude") == null)
            {
                // Do nothing
            }
            // 年収を更新
            contact1["annualincome"] = new Money(9999m);
            contact1.Attributes.Remove("annualincome"); // 更新取り消し
            contact1.Attributes["lastname"] = null; //null値で更新
            // customer(所属取引先企業/上司)の設定(Lookupも同じ)
            contact1.Attributes["parentcustomerid"] = new EntityReference("account", new Guid("F718680D-4BFA-E011-85FA-00155D0A0B14"));
            UpdateRequest updateRequst = new UpdateRequest()
            {
                Target = contact1
            };
            UpdateResponse updateResponse = service.Execute(updateRequst) as UpdateResponse;

            contact1 = service.Retrieve("contact", contact1id, new ColumnSet(true));

            // 取引先担当者の非アクティブ化 Execute (SetStateRequest)
            contact1 = new Entity("contact");
            SetStateRequest setstateRequest = new SetStateRequest();
            setstateRequest.EntityMoniker = new EntityReference("contact", contact1id);
            setstateRequest.State = new OptionSetValue(1);
            setstateRequest.Status = new OptionSetValue(-1); // 既定のステータス
            service.Execute(setstateRequest);

            // 複数レコード検索 RetrieveMultipleRequest
            // QueryExpression や FetchExpressionでレコードを検索
            QueryExpression query = new QueryExpression("contact");
            query.Criteria.Filters.Add(new FilterExpression()
            {
                FilterOperator = LogicalOperator.And,
                Conditions =
                {
                    new ConditionExpression("firstname", ConditionOperator.Equal, "名2")
                }
            });
            query.ColumnSet = new ColumnSet("firstname", "lastname");
            RetrieveMultipleRequest retrieveMultipleRequest = new RetrieveMultipleRequest()
            {
                Query = query,
            };
            RetrieveMultipleResponse retrieveMultipleResponse = service.Execute(retrieveMultipleRequest) as RetrieveMultipleResponse;
            EntityCollection results = retrieveMultipleResponse.EntityCollection;

            foreach (var result in results.Entities)
            {
                Console.WriteLine("{0} {1}", result.GetAttributeValue<string>("firstname"), result.GetAttributeValue<string>("lastname"));
            }

            // 取引先担当者の削除 DeleteRequest
            DeleteRequest deleteRequest = new DeleteRequest()
            {
                Target = new EntityReference("contact", contact1id)
            };
            DeleteResponse deleteResponse = service.Execute(deleteRequest) as DeleteResponse;
        }

        /// <summary>  
        /// Crm On-Premise に接続する  
        /// </summary>  
        /// <param name="server">サーバー名</param>  
        /// <param name="orgname">組織名</param>  
        /// <returns>OrganizationServiceProxy のインスタンス</returns>  
        public static OrganizationServiceProxy GetOrganizationService(string server, string orgname)
        {
            string endpointaddress = string.Format("http://{0}/{1}/XRMServices/2011/Organization.svc", server, orgname);
            OrganizationServiceProxy organizationService = new OrganizationServiceProxy(new Uri(endpointaddress), null,
                new System.ServiceModel.Description.ClientCredentials(), null);

            return organizationService;
        } 
    }
}

3. まとめ

今回の説明は以上です。 Organization Service を使用すると、CRM 4.0 の CrmService や MetadataService と同様の操作が実現できます。