Dynamics CRM 4.0でエンティティのデータを操作するのではなく、エンティティや属性のメタデータを使用する場合はメタデータサービス(MetadataService) を使用します。今回の記事では、エンティティや属性のメタデータを作成、更新および削除をするサンプルを掲載します。

サンプルの動作確認はIFD構成の環境で行っています。IFD構成やAD構成のMetadataServiceインスタンスの作成方法の詳細は、[DynamicsCRM] MetadaServiceを使用してエンティティのメタデータを取得する を参照してください。

動作確認環境

  • 確認環境:Windows Server 2003 に IFD構成の Dynamics CRM 4.0をインストール
  • 開発環境:Visual Studio 2008 Professional
  • .NET 3.0

1. ソリューションの作成

Visual Studio を起動し、空のソリューションを作成します。本サンプルはコンソールアプリケーションとして開発します。ソリューションエクスプローラを右クリックし、コンソールプロジェクトを追加します。動作には、Dynamics CRM SDK に付属する、microsoft.crm.sdk.dll、microsoft.crm.sdktypeproxy.dllおよび、System.Web.Service.dll の参照が必要ですので、プロジェクトの参照で追加してします。

1.1 CrmDiscoveryService 用プロキシクラスの作成

IFD構成では、一度CrmDiscovryServiceに接続して認証トークンを取得した後、MetadataService を作成します。そのため、 CrmDiscoveryService を使用できるように、Dynamics CRM SDK に付属するwsdlフォルダのcrmdiscoveryservice.wsdlからプロキシクラスを作成します。

プロキシクラスは次のSDKのwsdlフォルダに移動して次のコマンドで作成しました。

wsdl /namespace:Microsoft.Crm.Sdk.Discovery  crmdiscoveryservice.wsdl

作成したプロキシクラスCrmDiscoveryService.csをプロジェクトに含めます。

2.MetadataServiceの作成プログラム

IFD構成のメタデータサービスは次のプログラムで作成します。AD認証の場合は[DynamicsCRM] MetadaServiceを使用してエンティティのメタデータを取得する で紹介されているGetMetadataService メソッドを参照してください。

/// <summary>
/// IFD構成用
/// </summary>
/// <param name="discoveryServerUrl"></param>
/// <param name="organizationName"></param>
/// <param name="domain"></param>
/// <param name="username"></param>
/// <param name="password"></param>
/// <returns></returns>
public static MetadataService GetMetadataServiceByIFD(string discoveryServerUrl, string organizationName, string domain, string username, string password)
{
    string userid = domain + @"\" + username;

    UriBuilder uriBuilder = new UriBuilder(discoveryServerUrl);
    uriBuilder.Path = "/MSCRMServices/2007/SPLA/CrmDiscoveryService.asmx";
    CrmDiscoveryService disco = new CrmDiscoveryService();
    disco.Url = uriBuilder.Uri.ToString();

    disco.UseDefaultCredentials = false;
    disco.Credentials = new NetworkCredential(username, password, domain);

    RetrieveOrganizationsRequest orgRequest = new RetrieveOrganizationsRequest();
    orgRequest.UserId = userid;
    orgRequest.Password = password;
    RetrieveOrganizationsResponse orgResponse =
                (RetrieveOrganizationsResponse)disco.Execute(orgRequest);

    bool found = false;
    string serviceUrl = string.Empty;
    string metadataServiceUrl = string.Empty;
    foreach (OrganizationDetail orgdetail in orgResponse.OrganizationDetails)
    {
        if (orgdetail.OrganizationName == organizationName)
        {
            found = true;
            serviceUrl = orgdetail.CrmServiceUrl;
            metadataServiceUrl = orgdetail.CrmMetadataServiceUrl;
            break;
         }
    }
    if (found == false) return null;

    RetrieveCrmTicketRequest ticketRequest = new RetrieveCrmTicketRequest();
    ticketRequest.OrganizationName = organizationName;
    ticketRequest.UserId = userid;
    ticketRequest.Password = password;
    RetrieveCrmTicketResponse ticketResponse =
                (RetrieveCrmTicketResponse)disco.Execute(ticketRequest);

    CrmAuthenticationToken token = new CrmAuthenticationToken();
    token.AuthenticationType = 2; // IFD, ADの場合0
    token.OrganizationName = organizationName;
    token.CrmTicket = ticketResponse.CrmTicket;

    MetadataService service = new MetadataService();
    service.Url = metadataServiceUrl;
    service.CrmAuthenticationTokenValue = token;
    service.UseDefaultCredentials = true;

    return service;

}

3. カスタムエンティティと属性のメタデータの操作

new_zaikoというスキーマ名のカスタムエンティティのメタデータを操作します。

3.1 カスタムエンティティの作成

new_zaikoというカスタムエンティティを使用します。CrmLabelクラス作成用のユーティリティメソッドも定義します。

/// <summary>
/// 在庫エンティティを作成する
/// </summary>
/// <param name="service"></param>
public static void CreateCustomEntity(MetadataService service)
{
    EntityMetadata metadata = new EntityMetadata();
    metadata.SchemaName = "new_zaiko";
    metadata.DisplayName = CreateCrmLabel("在庫");
    metadata.DisplayCollectionName = CreateCrmLabel("在庫(複数)");
    metadata.Description = CreateCrmLabel("在庫の説明");
    // エンティティのデータはユーザ所有
    metadata.OwnershipType = new CrmOwnershipTypes(OwnershipTypes.UserOwned);

    StringAttributeMetadata stringMetadata = new StringAttributeMetadata();
    stringMetadata.SchemaName = "new_name";
    stringMetadata.DisplayName = CreateCrmLabel("商品");
    stringMetadata.Description = CreateCrmLabel("商品の説明");
    stringMetadata.RequiredLevel = new CrmAttributeRequiredLevel(AttributeRequiredLevel.Required);
    stringMetadata.MaxLength = new CrmNumber(50);

    CreateEntityRequest request = new CreateEntityRequest();
    request.Entity = metadata;
    request.PrimaryAttribute = stringMetadata;
    request.HasNotes = true;
    CreateEntityResponse response = (CreateEntityResponse)  service.Execute(request);
    Console.WriteLine(response.EntityId.Value);
}

public static CrmLabel CreateCrmLabel(string label)
{
    int languageCode = 1041;
    CrmLabel crmlabel = new CrmLabel();
    crmlabel.LocLabels = new LocLabel[] { new LocLabel(label, new CrmNumber(languageCode)) };
    return crmlabel;
}

3.2 カスタムエンティティメタデータの更新

カスタムエンティティのメタデータDisplayNameを変更します。カスタムエンティティのメタデータは変更できる項目は限られています。

/// <summary>
/// エンティティを更新する
/// Description, DisplayCollectionName,DisplayName,DuplicateDetection,IsAvailableOffline
/// のみ更新可能
/// </summary>
/// <param name="service"></param>
public static void UpdateCustomEntity(MetadataService service)
{
    EntityMetadata metadata = new EntityMetadata();
    metadata.LogicalName = "new_zaiko";

    metadata.DisplayName = CreateCrmLabel("在庫2");

    UpdateEntityRequest request = new UpdateEntityRequest();
    request.Entity = metadata;

    service.Execute(request);
}

3.3 カスタムエンティティの削除

/// <summary>
/// エンティティを削除する
/// </summary>
/// <param name="service"></param>
public static void DeleteCustomEntity(MetadataService service)
{
    DeleteEntityRequest request = new DeleteEntityRequest();
    request.LogicalName = "new_zaiko";

    service.Execute(request);
}

3.3 属性メタデータの作成

new_booleanという属性をカスタムエンティティnew_zaikoに追加します。

/// <summary>
/// 属性を追加する
/// </summary>
/// <param name="service"></param>
public static void AddCustomEntityAttribute(MetadataService service)
{
    BooleanAttributeMetadata booleanMetadata = new BooleanAttributeMetadata();
    booleanMetadata.SchemaName = "new_boolean";
    booleanMetadata.DisplayName = CreateCrmLabel("真偽値");
    booleanMetadata.Description = CreateCrmLabel("真偽値属性です");
    booleanMetadata.RequiredLevel = new CrmAttributeRequiredLevel(AttributeRequiredLevel.Recommended);
    booleanMetadata.TrueOption = new Option();
    booleanMetadata.TrueOption.Value = new CrmNumber(1);
    booleanMetadata.TrueOption.Label = CreateCrmLabel("はい");
    booleanMetadata.FalseOption = new Option();
    booleanMetadata.FalseOption.Value = new CrmNumber(0);
    booleanMetadata.FalseOption.Label = CreateCrmLabel("いいえ");

    CreateAttributeRequest request = new CreateAttributeRequest();
    request.EntityName = "new_zaiko";
    request.Attribute = booleanMetadata;

    service.Execute(request);
}

3.4 属性メタデータの更新

属性new_nameのメタデータを更新します。

/// <summary>
/// スキーマ名new_nameのロジカル名(スキーマ名をすべて小文字)を指定して
/// 属性を更新
/// </summary>
/// <param name="service"></param>
public static void UpdateCustomEntityAttribute(MetadataService service)
{
    StringAttributeMetadata stringMetadata = new StringAttributeMetadata();
    stringMetadata.LogicalName = "new_name";
    stringMetadata.DisplayName = CreateCrmLabel("商品/備品");
    stringMetadata.Description = CreateCrmLabel("商品/備品の説明");

    // 属性を追加
     UpdateAttributeRequest request = new UpdateAttributeRequest();
    request.EntityName = "new_zaiko";
    request.Attribute = stringMetadata;

    service.Execute(request);
}

3.4 実行処理

カスタムエンティティを作成、メタデータの操作、エンティティの削除をする一連の処理を行うようにMainメソッドを記述して実行し、動作することを確認します。

static void Main(string[] args)
{
    MetadataService service = GetMetadataServiceByIFD("http://crmorg02.vs2k3.crm.local/", "crmorg02", "crm", "admin", "password");
    CreateCustomEntity(service);
    UpdateCustomEntityAttribute(service);
    AddCustomEntityAttribute(service);
    UpdateCustomEntity(service);
    //DeleteCustomEntity(service);
    Console.ReadLine();
}

 4. まとめ

説明は以上です。メタデータサービスを使用すると、カスタムアプリケーションでエンティティや属性のメタデータを操作できるようになります。ちなみにサンプルには掲載していませんが、属性の削除は DeleteAttributeRequest クラスを使用します。