Code Copied

Dynamics CRM编程系列(3)Field创建

1. 温故知新

上一节我们讲述了如何创建一个自定义的Entity,并加入了Entity的一些Check,以确保Entity即使在创建失败的情况下能够得到有用的反馈信息。
Entity创建有3个基本的步骤:
1. 初始化CRM Organization Service
2. 创建CreateEntityRequest对象,并初始化Entity属性和PrimaryAttribute属性
3. 执行CreateEntityRequest请求

在创建Entity时,仅提供了一个Primary Field字段,根据业务的需要,我们还有很多字段要添加到自定义的Entity当中。

2. CRM创建字段示例

在SDK代码中已经提供了创建Field的的方法,我们就以SDK的示例开始本篇的内容。

SDK代码路径:SDK\SampleCode\CS\Metadata\Entities\CreateUpdateEntityMetadata.cs

参照示例代码的CreateAttributeRequest片段,构建1个CreateSampleField方法。

/// <summary>
/// 创建示例Field
/// </summary>
/// <param name="entityName">Entity的LogicalName</param>
/// <param name="schemName">Field的SchemName</param>
/// <param name="displayName">Field的DisplayName</param>
/// <param name="decription">Field的描述</param>
/// <param name="requiredLevel">Field的</param>
public OrganizationResponse CreateSampleField(string entityName, string schemName, string displayName, string decription, AttributeRequiredLevel requiredLevel)
{
    var request = new CreateAttributeRequest
    {
        EntityName = entityName,
        Attribute = new StringAttributeMetadata
        {
            SchemaName = schemName,
            RequiredLevel = new AttributeRequiredLevelManagedProperty(requiredLevel),
            MaxLength = 100,
            Format = StringFormat.Text,
            DisplayName = new Label(displayName, 1033),
            Description = new Label(decription, 1033)
        }
    };
    return Service.Execute(request);
}

在CRM2011之前的版本中,Field被称之为Attribute,在2011的SDK中仍然使用了Attribute,但是在CRM的画面中已经将Attribute更改为Field了。

创建对应的Unit Test方法TestCreateField。

[TestMethod]
public void TestCreateSampleField()
{
    var metadataHelper = new FieldMetadataHelper();
    var response = metadataHelper.CreateSampleField(
        "new_bankaccount",          // Entity名称
        "new_accountcode",          // Filed名称
        "Account Code",             // Field显示名称
        string.Empty,               // Field描述
        AttributeRequiredLevel.None // 字段需要级别
    );

    Assert.IsNotNull(response);
    Debug.WriteLine("EntityId:" + response.Results["AttributeId"]);
}

在Debug模式下运行Unit Test。

image

和CreateEntity方法不同,CreateField方法的ResponseName为”CreateField”,并且Results属性只有一个key,即“AttributeId”,这个key对应的value是一个GUID。

image

3. CRM字段数据类型

通过CreateField方法已经成功创建了1个Single Line of Text类型的Field,但该方法有些局限:只能创建Single Line of Text类型的字段。
为了能够让CreateField方法兼容其它类型,我们需要充分了解CRM的Field数据类型。

Field数据类型定义

CRM提供了10种可自定义的Field数据类型(摘录自Working with Dynamics CRM 2011第214页):

  • Single Line of Text(单行文本)    Stores text and numeric data between 1 and 4,000 characters in length in one field.
  • Option Set(选项集)    Allows you to specify a predefined list of values for the field. Users see
    a drop-down list on the form.
  • Two Options(是非选项)    Stores data as one of two values, 0 or 1. In Microsoft Dynamics CRM, you can relabel the 0 and 1 values so that users see Yes and No, True and False, and so on. Many people use the words Boolean or bit when referring to this data type.
  • Whole Number(整数)    Allows you to store only whole numbers, such as –2, –1, 0, 1, 2,
    and so on. Values can range from –2,147,483,648 to 2,147,483,647.
  • Floating Point Number(浮点数)    Stores approximate numeric values with a variable number of decimals, such as 1.3333 or 3.14. Values can range from –100,000,000,000.00000 to 100,000,000,000.00000.
  • Decimal Number(高精度浮点数)    Stores exact numeric values with decimals such as 1.5. Values can
    range from –100,000,000,000.00000 to 100,000,000,000.00000.
  • Currency(货币)    Stores currency amounts. You will have the ability to set the exact precision of currency fields or select Pricing Decimal Precision or Currency Precision. The Setup program of Microsoft Dynamics CRM sets the default value in the Pricing Decimal Precision to 2. The Currency Precision option will display the amount stored in the field in the correct precision for the currency selected on the record. Values can range from –922,337,203,685,477.0000 to 922,337,203,685,477.0000.
  • Multiple Lines of Text(多行文本)    Stores text and numeric data between 1 and 1,048,576 characters in length in one field.
  • Date and Time(日期)     Stores date and time data.
  • lookup(引用查找)    System data type that Stores information about related records.

在CRM 2011之前的版本中,Field数据类型的名称更贴近SQL Server的数据类型,例如:single line of text在之前的版本中为navrchar,currency在之前的版本中为money。

特定的字段属性

在CRM中字段拥有一些共通的属性,例如:Name, DisplayName, RequiredLevel等。但对于不同数据类型的字段,它们都拥有一些特定的属性。

Field属性 适用的数据类型
Format single line of text, whole number, and date and time
Maximum Length single line of text and multiple lines of text
Use Existing Option Set option set
Options option set and two options
Default Value option set and two options
Minimum Value whole number, floating point number, decimal number, and currency
Maximum Value whole number, floating point number, decimal number, and currency
Precision floating point number, decimal number, and currency
Target Record Type lookup
Relationship Name lookup
IME Mode

single line of text, whole number, floating point number, decimal
number, currency, multiple lines of text, and date and time

4. CRM不同类型字段的创建方法

根据上述的Field数据类型描述,我们可以为不同类型的Field提供创建方法。

创建Single Line of Text字段

Source:

/// <summary>
/// 创建Single Line of Text字段
/// </summary>
public OrganizationResponse CreateSingleLineOfTextField(
    string entityName,
    string schemName,
    string displayName,
    string decription,
    int maxLength,
    AttributeRequiredLevel requiredLevel)
{
    var request = new CreateAttributeRequest
    {
        EntityName = entityName,
        Attribute = new StringAttributeMetadata
        {
            SchemaName = schemName,
            RequiredLevel = new AttributeRequiredLevelManagedProperty(requiredLevel),
            MaxLength = maxLength,
            Format = StringFormat.Text,
            DisplayName = new Label(displayName, 1033),
            Description = new Label(decription, 1033)
        }
    };
    return Service.Execute(request);
}

UnitTest:

[TestMethod]
public void TestCreateSingleLineOfTextField()
{
    var metadataHelper = new FieldMetadataHelper();
    var response = metadataHelper.CreateSingleLineOfTextField(
        "new_bankaccount",          // Entity名称
        "new_singlelineoftext",     // Filed名称
        "Single Line of Text",      // Field显示名称
        string.Empty,               // Field描述
        100,                        // Field最大长度
        AttributeRequiredLevel.None // 字段需要级别
    );

    Assert.IsNotNull(response);
    Debug.WriteLine("AttributeId:" + response.Results["AttributeId"]);
}

Result:

image

创建Multiple Lines of Text字段

Source:

/// <summary>
/// 创建Multiple Lines of Text字段
/// </summary>
public OrganizationResponse CreateMultipleLinesOfTextField(
    string entityName,
    string schemName,
    string displayName,
    string decription,
    int maxLength,
    AttributeRequiredLevel requiredLevel)
{
    var request = new CreateAttributeRequest
    {
        EntityName = entityName,
        Attribute = new MemoAttributeMetadata()
        {
            SchemaName = schemName,
            RequiredLevel = new AttributeRequiredLevelManagedProperty(requiredLevel),
            MaxLength = maxLength,
            Format = StringFormat.Text,
            DisplayName = new Label(displayName, 1033),
            Description = new Label(decription, 1033)
        }
    };
    return Service.Execute(request);
}

UnitTest:

[TestMethod]
public void TestCreateMultipleLinesOfTextField()
{
    var metadataHelper = new FieldMetadataHelper();
    var response = metadataHelper.CreateSingleLineOfTextField(
        "new_bankaccount",          // Entity名称
        "new_multiplelinesoftext",  // Filed名称
        "Multiple Lines of Text",   // Field显示名称
        string.Empty,               // Field描述
        4000,                       // Field最大长度
        AttributeRequiredLevel.None // 字段需要级别
    );

    Assert.IsNotNull(response);
    Debug.WriteLine("AttributeId:" + response.Results["AttributeId"]);
}

Result:

image

创建Whole Number字段

Source:

/// <summary>
/// 创建Whole Number字段
/// </summary>
public OrganizationResponse CreateWholeNumberField(
    string entityName,
    string schemName,
    string displayName,
    string decription,
    int? minValue,
    int? maxValue,
    AttributeRequiredLevel requiredLevel)
{
    var request = new CreateAttributeRequest
    {
        EntityName = entityName,
        Attribute = new IntegerAttributeMetadata()
        {
            SchemaName = schemName,
            RequiredLevel = new AttributeRequiredLevelManagedProperty(requiredLevel),
            DisplayName = new Label(displayName, 1033),
            Description = new Label(decription, 1033),
            MinValue = minValue,
            MaxValue = maxValue
        }
    };
    return Service.Execute(request);
}

UnitTest:

[TestMethod]
public void TestCreateWholeNumberField()
{
    var metadataHelper = new FieldMetadataHelper();
    var response = metadataHelper.CreateWholeNumberField(
        "new_bankaccount",          // Entity名称
        "new_wholenumber",          // Filed名称
        "Whole Number",             // Field显示名称
        string.Empty,               // Field描述
        1,                          // Field最小值
        1000,                       // Field最大值
        AttributeRequiredLevel.None // 字段需要级别
    );

    Assert.IsNotNull(response);
    Debug.WriteLine("AttributeId:" + response.Results["AttributeId"]);
}

Result:

image

创建Floating Point Number字段

Source:

/// <summary>
/// 创建Floating Point Number字段
/// </summary>
public OrganizationResponse CreateFloatingPointNumberField(
    string entityName,
    string schemName,
    string displayName,
    string decription,
    double? minValue,
    double? maxValue,
    AttributeRequiredLevel requiredLevel)
{
    var request = new CreateAttributeRequest
    {
        EntityName = entityName,
        Attribute = new DoubleAttributeMetadata()
        {
            SchemaName = schemName,
            RequiredLevel = new AttributeRequiredLevelManagedProperty(requiredLevel),
            DisplayName = new Label(displayName, 1033),
            Description = new Label(decription, 1033),
            MinValue = minValue,
            MaxValue = maxValue
        }
    };
    return Service.Execute(request);
}

UnitTest:

[TestMethod]
public void TestCreateFloatingPointNumberField()
{
    var metadataHelper = new FieldMetadataHelper();
    var response = metadataHelper.CreateFloatingPointNumberField(
        "new_bankaccount",          // Entity名称
        "new_floatingpointnumber",  // Filed名称
        "Floating Point Number",    // Field显示名称
        string.Empty,               // Field描述
        -1000000.00,                // Field最小值
        1000000.00,                 // Field最大值
        AttributeRequiredLevel.None // 字段需要级别
    );

    Assert.IsNotNull(response);
    Debug.WriteLine("AttributeId:" + response.Results["AttributeId"]);
}

Result:

image

创建Decimal字段

Source:

/// <summary>
/// 创建Decimal字段
/// </summary>
public OrganizationResponse CreateDecimalField(
    string entityName,
    string schemName,
    string displayName,
    string decription,
    int? precision,
    AttributeRequiredLevel requiredLevel)
{
    var request = new CreateAttributeRequest
    {
        EntityName = entityName,
        Attribute = new DecimalAttributeMetadata()
        {
            SchemaName = schemName,
            RequiredLevel = new AttributeRequiredLevelManagedProperty(requiredLevel),
            DisplayName = new Label(displayName, 1033),
            Description = new Label(decription, 1033),
            Precision = precision
        }
    };
    return Service.Execute(request);
}

UnitTest:

[TestMethod]
public void TestCreateDecimalField()
{
    var metadataHelper = new FieldMetadataHelper();
    var response = metadataHelper.CreateDecimalField(
        "new_bankaccount",          // Entity名称
        "new_decimal",              // Filed名称
        "Decimal",                  // Field显示名称
        string.Empty,               // Field描述
        2,                          // Field小数精度
        AttributeRequiredLevel.None // 字段需要级别
    );

    Assert.IsNotNull(response);
    Debug.WriteLine("AttributeId:" + response.Results["AttributeId"]);
}

Result:

image

创建DateTime字段

Source:

/// <summary>
/// 创建DateTime字段
/// </summary>
public OrganizationResponse CreateDateTimeField(
    string entityName,
    string schemName,
    string displayName,
    string decription,
    AttributeRequiredLevel requiredLevel)
{
    var request = new CreateAttributeRequest
    {
        EntityName = entityName,
        Attribute = new DateTimeAttributeMetadata()
        {
            SchemaName = schemName,
            RequiredLevel = new AttributeRequiredLevelManagedProperty(requiredLevel),
            DisplayName = new Label(displayName, 1033),
            Description = new Label(decription, 1033),
            // Set extended properties
            Format = DateTimeFormat.DateOnly,
            ImeMode = ImeMode.Disabled
        }
    };
    return Service.Execute(request);
} 

UnitTest:

[TestMethod]
public void TestCreateDateTimeField()
{
    var metadataHelper = new FieldMetadataHelper();
    var response = metadataHelper.CreateDateTimeField(
        "new_bankaccount",          // Entity名称
        "new_datetime",             // Filed名称
        "DateTime",                 // Field显示名称
        string.Empty,               // Field描述
        AttributeRequiredLevel.None // 字段需要级别
    );

    Assert.IsNotNull(response);
    Debug.WriteLine("AttributeId:" + response.Results["AttributeId"]);
}

Result:

image

创建Two Options字段

Source:

/// <summary>
/// 创建Two Options字段
/// </summary>
public OrganizationResponse CreateTwoOptionsField(
    string entityName,
    string schemName,
    string displayName,
    string decription,
    IDictionary<string, int> options,
    AttributeRequiredLevel requiredLevel)
{

    if (options.Count != 2)
    {
        throw new ArgumentException("The options argument should have two options");
    }
    OptionMetadataCollection collection = GetOptionMetadataCollection(options);
    var request = new CreateAttributeRequest
    {
        EntityName = entityName,
        Attribute = new BooleanAttributeMetadata()
        {
            SchemaName = schemName,
            RequiredLevel = new AttributeRequiredLevelManagedProperty(requiredLevel),
            DisplayName = new Label(displayName, 1033),
            Description = new Label(decription, 1033),
            OptionSet = new BooleanOptionSetMetadata(
                collection[0],  // true option
                collection[1]   // false option
            )
        }
    };
    return Service.Execute(request);
}

CreateTwoOptionsField方法引用了1个GetOptionMetadataCollection方法,这个方法如下:

/// <summary>
/// 获取OptionMetadataCollection
/// </summary>
private OptionMetadataCollection GetOptionMetadataCollection(IDictionary<string, int> options)
{
    IList<OptionMetadata> list = options.Select(opt => new OptionMetadata()
    {
        Label = new Label(opt.Key, 1033),
        Value = opt.Value
    }).ToList();
    var collection = new OptionMetadataCollection(list);
    return collection;
}

UnitTest:

[TestMethod]
public void TestCreateTwoOptionsField()
{
    var metadataHelper = new FieldMetadataHelper();
    var response = metadataHelper.CreateTwoOptionsField(
        "new_bankaccount",                              // Entity名称
        "new_twooptions",                               // Filed名称
        "Two Options",                                  // Field显示名称
        string.Empty,                                   // Field描述
        new Dictionary<string, int>{{"Yes",1},{"No",0}},// Two Options选项 
        AttributeRequiredLevel.None                     // 字段需要级别
    );

    Assert.IsNotNull(response);
    Debug.WriteLine("AttributeId:" + response.Results["AttributeId"]);
}

Result:

image

创建OptionSet字段

Source:

/// <summary>
/// 创建OptionSet字段
/// </summary>
public OrganizationResponse CreateOptionSetField(
    string entityName,
    string schemName,
    string displayName,
    string decription,
    IDictionary<string,int> options,
    bool isGlobal,
    AttributeRequiredLevel requiredLevel)
{
    OptionMetadataCollection collection = GetOptionMetadataCollection(options);

    var request = new CreateAttributeRequest
    {
        EntityName = entityName,
        Attribute = new PicklistAttributeMetadata()
        {
            SchemaName = schemName,
            RequiredLevel = new AttributeRequiredLevelManagedProperty(requiredLevel),
            DisplayName = new Label(displayName, 1033),
            Description = new Label(decription, 1033),
            OptionSet = new OptionSetMetadata(collection)
            {
                IsGlobal = isGlobal
            }
        }
    };
    return Service.Execute(request);
}

UnitTest:

[TestMethod]
public void TestCreateOptionSetField()
{
    var metadataHelper = new FieldMetadataHelper();
    var response = metadataHelper.CreateOptionSetField(
        "new_bankaccount",              // Entity名称
        "new_optionset",                // Filed名称
        "OptionSet",                    // Field显示名称
        string.Empty,                   // Field描述
        new Dictionary<string, int>     // OptionSet选项集 
        {
            {"Green", 1},
            {"Yellow", 2},
            {"Red", 3},
            {"Black", 4}
        }, 
        false,                          // IsGlobal
        AttributeRequiredLevel.None     // 字段需要级别
        );

    Assert.IsNotNull(response);
    Debug.WriteLine("AttributeId:" + response.Results["AttributeId"]);
}

Result:

image

创建Lookup字段

Source:

/// <summary>
/// 创建Lookup字段
/// </summary>
public OrganizationResponse CreateLookupField(
    string entityName,
    string schemName,
    string displayName,
    string decription,
    string referencedEntityName,
    string referencedAttributeName,
    string relationshipSchemName,
    AttributeRequiredLevel requiredLevel)
{
    CreateOneToManyRequest request = new CreateOneToManyRequest()
    {
        Lookup = new LookupAttributeMetadata()
        {
            Description = new Label(decription, 1033),
            DisplayName = new Label(displayName, 1033),
            SchemaName = schemName,
            RequiredLevel =
                new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.ApplicationRequired)
        },
        OneToManyRelationship = new OneToManyRelationshipMetadata()
        {
            CascadeConfiguration = new CascadeConfiguration()
            {
                Assign = CascadeType.Cascade,
                Delete = CascadeType.Cascade,
                Merge = CascadeType.Cascade,
                Reparent = CascadeType.Cascade,
                Share = CascadeType.Cascade,
                Unshare = CascadeType.Cascade
            },
            ReferencedEntity = referencedEntityName,
            ReferencedAttribute = referencedAttributeName,
            ReferencingEntity = entityName,
            SchemaName = relationshipSchemName
        }
    };
    return Service.Execute(request);
}

通过OneToManyRequest创建Lookup字段,并指定OneToManyRelationship,OneToManyRelationship必要的属性有以下几个:
1. CasacdeConfiguration: 级联配置
2. ReferencedEntity: 被关联的Entity逻辑名称
3. ReferencedAttribute: 被关联的Entity的主键字段逻辑名称
4. ReferencingEntity: 关联的Entity的逻辑名称
5. SchemanName: 关联关系的名称

UnitTest:

[TestMethod]
public void TestCreateLookupField()
{
    var metadataHelper = new FieldMetadataHelper();
    var response = metadataHelper.CreateLookupField(
        "new_bankaccount",              // Entity名称
        "new_lookup",                   // Filed名称
        "Lookup",                       // Field显示名称
        string.Empty,                   // Field描述
        "account",                      // 被关联的Entity名称
        "accountid",                    // 被关联的Entity主键字段名称
        "new_account_new_bankaccount",  // Relationship的名称
        AttributeRequiredLevel.None     // 字段需要级别
        );

    Assert.IsNotNull(response);
    Debug.WriteLine("AttributeId:" + response.Results["AttributeId"]);
}

Result:

image

image

5. CRM共通的字段创建方法

上面的示例展示了不同类型字段的创建方法,但要记住这么多字段的创建方法殊为不易,所有类型字段的创建应该共用一个入口。
根据不同字段类型的共同点和特定点,我们可以抽象一个FieldMetadata类。

FieldMedatada类:

/// <summary>
/// 字段元数据
/// </summary>
public class FieldMetadata
{
    #region 基础属性(必须)

    public string EntityName { get; set; }
    public string SchemName { get; set; }
    public string DisplayName { get; set; }
    public string Description { get; set; }
    public AttributeRequiredLevel RequiredLevel { get; set; }
    public FieldType FieldType { get; set; }

    #endregion

    #region 扩展属性(可选)

    /* SingleLineOfText, MultipleLinesOfText */
    public int MaxLength { get; set; }

    /* WholeNumber,FloatingPointNumber */
    public int? MinValue { get; set; }
    public int? MaxValue { get; set; }

    /* Decimal */
    public int? Precision { get; set; }

    /* TwoOptions, OptionSet */
    public IDictionary<string, int> Options { get; set; }

    /* OptionSet */
    public bool IsGlobal { get; set; }

    /* Lookup */
    public string ReferencedEntityName { get; set; }
    public string ReferencedAttributeName { get; set; }
    public string RelationshipSchemName { get; set; }

    #endregion
}

/// <summary>
/// 字段类型
/// </summary>
public enum FieldType
{
    SingleLineOfText,
    MultipleLinesOfText,
    WholeNumber,
    FloatingPointNumber,
    Decimal,
    DateTime,
    TwoOptions,
    OptionSet,
    Lookup
}

FieldMetadata类的属性分为两部分:一部分是基础属性,它们是各种字段的共通属性;另外一部分是扩展属性,它们是各种字段的特定属性。
在创建字段时,统一传入FieldMetadata对象,于是就有了共通的CreateField方法。

CreateField方法:

/// <summary>
/// 创建字段
/// </summary>
public OrganizationResponse CreateField(FieldMetadata fieldMetadata)
{

    OrganizationResponse response = null;
    switch (fieldMetadata.FieldType)
    {
        case FieldType.SingleLineOfText:
            response = CreateSingleLineOfTextField(
                fieldMetadata.EntityName,
                fieldMetadata.SchemName,
                fieldMetadata.DisplayName,
                fieldMetadata.Description,
                fieldMetadata.MaxLength,
                fieldMetadata.RequiredLevel);
            break;
        case FieldType.MultipleLinesOfText:
            response = CreateMultipleLinesOfTextField(
                fieldMetadata.EntityName,
                fieldMetadata.SchemName,
                fieldMetadata.DisplayName,
                fieldMetadata.Description,
                fieldMetadata.MaxLength,
                fieldMetadata.RequiredLevel);
            break;
        case FieldType.DateTime:
            response = CreateDateTimeField(
                fieldMetadata.EntityName,
                fieldMetadata.SchemName,
                fieldMetadata.DisplayName,
                fieldMetadata.Description,
                fieldMetadata.RequiredLevel);
            break;
        case FieldType.WholeNumber:
            response = CreateWholeNumberField(
                fieldMetadata.EntityName,
                fieldMetadata.SchemName,
                fieldMetadata.DisplayName,
                fieldMetadata.Description,
                fieldMetadata.MinValue,
                fieldMetadata.MaxValue,
                fieldMetadata.RequiredLevel);
            break;
        case FieldType.FloatingPointNumber:
            response = CreateFloatingPointNumberField(
                fieldMetadata.EntityName,
                fieldMetadata.SchemName,
                fieldMetadata.DisplayName,
                fieldMetadata.Description,
                fieldMetadata.MinValue,
                fieldMetadata.MaxValue,
                fieldMetadata.RequiredLevel);
            break;
        case FieldType.Decimal:
            response = CreateDecimalField(
                fieldMetadata.EntityName,
                fieldMetadata.SchemName,
                fieldMetadata.DisplayName,
                fieldMetadata.Description,
                fieldMetadata.Precision,
                fieldMetadata.RequiredLevel);
            break;
        case FieldType.TwoOptions:
            response = CreateTwoOptionsField(
                fieldMetadata.EntityName,
                fieldMetadata.SchemName,
                fieldMetadata.DisplayName,
                fieldMetadata.Description,
                fieldMetadata.Options,
                fieldMetadata.RequiredLevel);
            break;
        case FieldType.OptionSet:
            response = CreateOptionSetField(
                fieldMetadata.EntityName,
                fieldMetadata.SchemName,
                fieldMetadata.DisplayName,
                fieldMetadata.Description,
                fieldMetadata.Options,
                fieldMetadata.IsGlobal,
                fieldMetadata.RequiredLevel);
            break;
        case FieldType.Lookup:
            response = CreateLookupField(
                fieldMetadata.EntityName,
                fieldMetadata.SchemName,
                fieldMetadata.DisplayName,
                fieldMetadata.Description,
                fieldMetadata.ReferencedEntityName,
                fieldMetadata.ReferencedAttributeName,
                fieldMetadata.RelationshipSchemName,
                fieldMetadata.RequiredLevel);
            break;

    }
    return response;
}

CreateField方法将不同类型字段的创建方法都包装进来了,这样就实现了不同类型字段的创建共用一个入口。

6. 总结

1. 熟悉CRM的10种Field数据类型
2. 熟悉CRM不同Field之间的差异性
3. Field创建过程:IOrganizationService执行CreateAttrbiuteRequest对象请求,并返回OrganizationResponse对象

image

7. 参考和源码

参考链接:https://msdn.microsoft.com/en-us/library/gg509014.aspx
下载链接:http://blog.64cm.com/source/CRM/Dynamics CRM Programming(3).zip
项目git链接:https://github.com/crmug/DynamicsCrm