다음을 통해 공유


메타데이터에 대한 변경 내용을 검색합니다.

 

게시 날짜: 2017년 1월

적용 대상: Dynamics 365 (online), Dynamics 365 (on-premises), Dynamics CRM 2016, Dynamics CRM Online

Microsoft.Xrm.Sdk.Metadata.Query 네임스페이스의 클래스와 RetrieveMetadataChangesRequestRetrieveMetadataChangesResponse 클래스를 사용하면 효율적인 메타데이터 쿼리를 작성하고 시간이 지남에 따라 발생하는 메타데이터의 변경 내용을 캡처할 수 있습니다.

이 문서에서 참조하는 모든 코드 예제는 샘플: 쿼리 메타데이터 및 변경 검색에 있습니다.

기술 문서 JavaScript를 사용하여 메타데이터 쿼리에는 클라이언트 쪽 코드에서 개체 및 메시지를 사용하는 JavaScript 라이브러리를 제공합니다.

이 항목의 내용

메타데이터 사용 전략

필요한 메타데이터만 검색

새 메타데이터 또는 변경된 메타데이터 검색

삭제된 메타데이터에 대한 정보 검색

메타데이터 사용 전략

메타데이터를 사용하면 Microsoft Dynamics 365 데이터 모델이 변경될 때 적용하는 응용 프로그램을 만들 수 있습니다. 메타데이터는 다음과 같은 유형의 응용 프로그램에 중요합니다.

  • 클라이언트 응용 프로그램용 UI

  • Dynamics 365 데이터를 외부 시스템에 매핑해야 하는 통합 도구

  • 개발 도구

Microsoft.Xrm.Sdk.Metadata.Query 네임스페이스의 클래스를 사용하면 간단한 쿼리와 영구 메타데이터 캐시 사이의 어딘가에 존재하는 디자인을 구현할 수 있습니다.

간단한 쿼리

간단한 쿼리의 예는 Microsoft Dynamics 365 옵션 집합(선택 목록) 특성의 현재 옵션을 표시하는 선택 컨트롤을 제공하는 사용자 지정 웹 리소스 UI가 있는 경우입니다. 사용 가능한 옵션이 변경도면 업데이트해야 하므로 이러한 옵션을 하드 코딩하지 않는 것이 좋습니다. 대신 메타데이터에서 이러한 옵션 값과 레이블을 검색하는 쿼리를 구성할 수 있습니다.

Microsoft.Xrm.Sdk.Metadata.Query 클래스를 사용하여 이 데이터를 직접 Microsoft Dynamics 365 응용 프로그램 캐시에서 검색할 수 있으므로 이 데이터를 캐시할 필요가 없습니다.

영구 메타데이터 캐시

Microsoft Dynamics 365 서버와의 연결이 끊어진 동안 작업할 수 있어야 하거나 모바일 응용 프로그램과 같이 클라이언트와 서버 간 제한된 네트워크 대역폭에 민감한 응용 프로그램이 있을 경우 영구 메타데이터 캐시를 구현하는 것이 좋습니다.

영구 메타데이터 캐시를 사용하면 응용 프로그램은 처음 연결할 때 필요한 모든 메타데이터를 쿼리해야 합니다. 그런 다음 응용 프로그램에 해당 데이터를 저장합니다. 다음에 응용 프로그램이 서버에 연결하면 전송할 데이터가 훨씬 적은 마지막 쿼리 이후의 차이만 검색한 후 응용 프로그램을 로드할 때 변경 내용을 메타데이터 캐시에 병합할 수 있습니다.

메타데이터 변경 내용을 폴링하는 빈도는 응용 프로그램에 대한 메타데이터의 예상 휘발성과 응용 프로그램이 계속 실행되는 시간에 따라 달라집니다. 메타데이터가 변경되면 검색하는 데 사용할 수 있는 사용 가능한 이벤트가 없습니다. 삭제된 메타데이터 변경 내용이 저장되는 일 수에 대한 제한이 있으며 해당 한도를 벗어나는 변경에 대한 요청을 수행하려면 메타데이터 캐시를 전체 다시 초기화해야 합니다. 자세한 내용은 삭제된 메타데이터 만료를 참조하십시오.

변경 내용이 없을 경우 쿼리는 신속하게 응답해야 하고 다시 전송되는 데이터가 없습니다. 하지만 변경 내용이 있을 경우, 특히 캐시에서 제거되어야 하는 관련 메타데이터 항목이 있을 경우 요청을 완료하는 데 시간이 추가로 소요될 수 있습니다.추가 정보:삭제된 메타데이터를 검색할 때의 성능

필요한 메타데이터만 검색

메타데이터는 응용 프로그램을 시작할 때 종종 검색되거나 동기화되므로 응용 프로그램을 로드하는 데 걸리는 시간에 영향을 줄 수 있습니다. 처음으로 메타데이터를 검색하는 모바일 응용 프로그램의 경우 특히 그렇습니다. 필요한 메타데이터만 검색하는 것은 잘 수행되는 응용 프로그램을 만드는 데 매우 중요합니다.

EntityQueryExpression 클래스는 엔터티 데이터를 검색하기 위해 복잡한 쿼리를 만드는 데 사용하는 QueryExpression 클래스와 일치하는 구조를 제공합니다.RetrieveAllEntitiesRequest, RetrieveEntityRequest, RetrieveAttributeRequest 또는 RetrieveRelationshipRequest 클래스와 달리 RetrieveMetadataChangesRequest에는 원하는 속성뿐만 아니라 반환할 데이터에 대한 특정 조건을 지정하는 데 사용할 수 있는 EntityQueryExpression 인스턴스를 허용하는 Query 매개 변수가 들어 있습니다.RetrieveMetadataChangesRequest를 사용하여 RetrieveAllEntitiesRequest를 사용하여 가져오는 메타데이터 전체 집합 또는 특정 특성에 대한 레이블을 반환할 수 있습니다.

필터 조건 지정

EntityQueryExpression.Criteria 속성은 해당 값에 따라 엔터티 속성을 필터링하는 조건을 정의할 수 있는 MetadataConditionExpression 개체 컬렉션이 포함된 MetadataFilterExpression을 허용합니다. 이러한 조건은 다음과 같은 연산자를 허용하는 MetadataConditionOperator를 사용합니다.

MetadataFilterExpression에는 조건을 평가할 때 And 또는 Or 논리를 적용할지 여부를 나타내는 LogicalOperator도 포함됩니다.

모든 속성이 필터 조건으로 사용될 수 있는 것은 아닙니다. 단순 데이터 유형, 열거형, BooleanManagedProperty 또는 AttributeRequiredLevelManagedProperty 유형을 나타내는 속성만 MetadataFilterExpression에서 사용할 수 있습니다.BooleanManagedProperty 또는 AttributeRequiredLevelManagedProperty를 지정하면 Value 속성만 평가됩니다.

다음 표에는 MetadataFilterExpression에서 사용할 수 없는 EntityMetadata 속성이 나와 있습니다.

Attributes

Description

DisplayCollectionName

DisplayName

ManyToManyRelationships

ManyToOneRelationships

OneToManyRelationships

Privileges

다음 예제에서는 제외할 엔터티 목록에 포함되지 않는 비교차 사용자 담당 엔터티 집합을 반환하는 MetadataFilterExpression을 보여 줍니다.



     // An array SchemaName values for non-intersect, user-owned entities that should not be returned.
     String[] excludedEntities = {
"WorkflowLog",
"Template",
"CustomerOpportunityRole",
"Import",
"UserQueryVisualization",
"UserEntityInstanceData",
"ImportLog",
"RecurrenceRule",
"QuoteClose",
"UserForm",
"SharePointDocumentLocation",
"Queue",
"DuplicateRule",
"OpportunityClose",
"Workflow",
"RecurringAppointmentMaster",
"CustomerRelationship",
"Annotation",
"SharePointSite",
"ImportData",
"ImportFile",
"OrderClose",
"Contract",
"BulkOperation",
"CampaignResponse",
"Connection",
"Report",
"CampaignActivity",
"UserEntityUISettings",
"IncidentResolution",
"GoalRollupQuery",
"MailMergeTemplate",
"Campaign",
"PostFollow",
"ImportMap",
"Goal",
"AsyncOperation",
"ProcessSession",
"UserQuery",
"ActivityPointer",
"List",
"ServiceAppointment"};

     //A filter expression to limit entities returned to non-intersect, user-owned entities not found in the list of excluded entities.
     MetadataFilterExpression EntityFilter = new MetadataFilterExpression(LogicalOperator.And);
     EntityFilter.Conditions.Add(new MetadataConditionExpression("IsIntersect", MetadataConditionOperator.Equals, false));
     EntityFilter.Conditions.Add(new MetadataConditionExpression("OwnershipType", MetadataConditionOperator.Equals, OwnershipTypes.UserOwned));
     EntityFilter.Conditions.Add(new MetadataConditionExpression("SchemaName", MetadataConditionOperator.NotIn, excludedEntities));
     MetadataConditionExpression isVisibileInMobileTrue = new MetadataConditionExpression("IsVisibleInMobile", MetadataConditionOperator.Equals, true);
     EntityFilter.Conditions.Add(isVisibileInMobileTrue);


' An array SchemaName values for non-intersect, user-owned entities that should not be returned.
                  Dim excludedEntities() As String =
                      {
                          "WorkflowLog",
                          "Template",
                          "CustomerOpportunityRole",
                          "Import",
                          "UserQueryVisualization",
                          "UserEntityInstanceData",
                          "ImportLog",
                          "RecurrenceRule",
                          "QuoteClose",
                          "UserForm",
                          "SharePointDocumentLocation",
                          "Queue",
                          "DuplicateRule",
                          "OpportunityClose",
                          "Workflow",
                          "RecurringAppointmentMaster",
                          "CustomerRelationship",
                          "Annotation",
                          "SharePointSite",
                          "ImportData",
                          "ImportFile",
                          "OrderClose",
                          "Contract",
                          "BulkOperation",
                          "CampaignResponse",
                          "Connection",
                          "Report",
                          "CampaignActivity",
                          "UserEntityUISettings",
                          "IncidentResolution",
                          "GoalRollupQuery",
                          "MailMergeTemplate",
                          "Campaign",
                          "PostFollow",
                          "ImportMap",
                          "Goal",
                          "AsyncOperation",
                          "ProcessSession",
                          "UserQuery",
                          "ActivityPointer",
                          "List",
                          "ServiceAppointment"
                      }

'A filter expression to limit entities returned to non-intersect, user-owned entities not found in the list of excluded entities.
Dim EntityFilter As New MetadataFilterExpression(LogicalOperator.And)
EntityFilter.Conditions.Add(New MetadataConditionExpression("IsIntersect", MetadataConditionOperator.Equals, False))
EntityFilter.Conditions.Add(New MetadataConditionExpression("OwnershipType", MetadataConditionOperator.Equals, OwnershipTypes.UserOwned))
EntityFilter.Conditions.Add(New MetadataConditionExpression("SchemaName", MetadataConditionOperator.NotIn, excludedEntities))
Dim isVisibileInMobileTrue As New MetadataConditionExpression("IsVisibleInMobile", MetadataConditionOperator.Equals, True)
EntityFilter.Conditions.Add(isVisibileInMobileTrue)

원하는 속성 지정

Properties 속성은 MetadataPropertiesExpression을 허용합니다. 모든 속성을 반환하려는 경우 MetadataPropertiesExpression.AllPropertiestrue로 설정하거나 결과에 포함하려는 속성을 정의하는 MetadataPropertiesExpression.PropertyNames에 문자열 모음을 제공할 수 있습니다.

반환된 강력한 유형의 개체에는 모든 속성이 포함되지만 요청한 속성만 데이터를 가집니다. 다음 몇 가지 예외를 제외하고 다른 모든 속성은 null이 됩니다. 메타데이터의 모든 항목에는 MetadataId, LogicalNameHasChanged 값이 해당 항목에 대해 있을 경우 포함됩니다. 요청한 Properties에 지정할 필요가 없습니다.

관리 코드를 사용하지 않고 XMLHttpRequest에서 반환된 responseXML을 실제로 구문 분석할 경우 각 속성에 대해 요소를 가져오지만 요청한 속성에만 데이터가 포함됩니다. 다음 XML은 IsVisibleInMobile이 요청한 유일한 속성일 때 반환되는 연락처 엔터티 메타데이터 xml을 보여 줍니다.

<a:EntityMetadata>
 <c:MetadataId>608861bc-50a4-4c5f-a02c-21fe1943e2cf</c:MetadataId>
 <c:HasChanged i:nil="true"/>
 <c:ActivityTypeMask i:nil="true"/>
 <c:Attributes i:nil="true"/>
 <c:AutoRouteToOwnerQueue i:nil="true"/>
 <c:CanBeInManyToMany i:nil="true"/>
 <c:CanBePrimaryEntityInRelationship i:nil="true"/>
 <c:CanBeRelatedEntityInRelationship i:nil="true"/>
 <c:CanCreateAttributes i:nil="true"/>
 <c:CanCreateCharts i:nil="true"/>
 <c:CanCreateForms i:nil="true"/>
 <c:CanCreateViews i:nil="true"/>
 <c:CanModifyAdditionalSettings i:nil="true"/>
 <c:CanTriggerWorkflow i:nil="true"/>
 <c:Description i:nil="true"/>
 <c:DisplayCollectionName i:nil="true"/>
 <c:DisplayName i:nil="true"/>
 <c:IconLargeName i:nil="true"/>
 <c:IconMediumName i:nil="true"/>
 <c:IconSmallName i:nil="true"/>
 <c:IsActivity i:nil="true"/>
 <c:IsActivityParty i:nil="true"/>
 <c:IsAuditEnabled i:nil="true"/>
 <c:IsAvailableOffline i:nil="true"/>
 <c:IsChildEntity i:nil="true"/>
 <c:IsConnectionsEnabled i:nil="true"/>
 <c:IsCustomEntity i:nil="true"/>
 <c:IsCustomizable i:nil="true"/>
 <c:IsDocumentManagementEnabled i:nil="true"/>
 <c:IsDuplicateDetectionEnabled i:nil="true"/>
 <c:IsEnabledForCharts i:nil="true"/>
 <c:IsImportable i:nil="true"/>
 <c:IsIntersect i:nil="true"/>
 <c:IsMailMergeEnabled i:nil="true"/>
 <c:IsManaged i:nil="true"/>
 <c:IsMappable i:nil="true"/>
 <c:IsReadingPaneEnabled i:nil="true"/>
 <c:IsRenameable i:nil="true"/>
 <c:IsValidForAdvancedFind i:nil="true"/>
 <c:IsValidForQueue i:nil="true"/>
 <c:IsVisibleInMobile>
  <a:CanBeChanged>false</a:CanBeChanged>
  <a:ManagedPropertyLogicalName>canmodifymobilevisibility</a:ManagedPropertyLogicalName>
  <a:Value>false</a:Value>
 </c:IsVisibleInMobile>
 <c:LogicalName>contact</c:LogicalName>
 <c:ManyToManyRelationships i:nil="true"/>
 <c:ManyToOneRelationships i:nil="true"/>
 <c:ObjectTypeCode i:nil="true"/>
 <c:OneToManyRelationships i:nil="true"/>
 <c:OwnershipType i:nil="true"/>
 <c:PrimaryIdAttribute i:nil="true"/>
 <c:PrimaryNameAttribute i:nil="true"/>
 <c:Privileges i:nil="true"/>
 <c:RecurrenceBaseEntityLogicalName i:nil="true"/>
 <c:ReportViewName i:nil="true"/>
 <c:SchemaName i:nil="true"/>
</a:EntityMetadata>

이후 릴리스에서는 요청하지 않은 속성에 대해 null 값을 가진 요소를 반환하지 않아 추가적인 효율이 달성될 수 있습니다. 이 XML을 구문 분석하는 코드를 작성하는 경우 동일한 쿼리에 대해 반환된 XML을 다음 XML로만 줄일 수 있습니다.

<a:EntityMetadata>
 <c:MetadataId>608861bc-50a4-4c5f-a02c-21fe1943e2cf</c:MetadataId>
 <c:IsVisibleInMobile>
  <a:CanBeChanged>false</a:CanBeChanged>
  <a:ManagedPropertyLogicalName>canmodifymobilevisibility</a:ManagedPropertyLogicalName>
  <a:Value>false</a:Value>
 </c:IsVisibleInMobile>
 <c:LogicalName>contact</c:LogicalName>
</a:EntityMetadata>

RetrieveAllEntitiesRequest를 사용하는 것과 마찬가지로 메타데이터가 계층적 구조에서 반환됩니다. 특정 특성 또는 관계에 액세스하려면 소속된 엔터티를 반환하는 쿼리를 만들어야 합니다. 특정 특성에 대한 데이터를 검색하려면 EntityMetadata.Attributes 속성을 EntityQueryExpression.Properties에 포함해야 합니다. 반환되는 엔터티 관계의 경우 EntityMetadata 속성 ManyToManyRelationships, ManyToOneRelationships 또는 OneToManyRelationships 중 하나 이상을 포함해야 합니다.

다음 예제에서는 요청된 엔터티에 대한 Attributes 속성을 반환합니다.


//A properties expression to limit the properties to be included with entities
MetadataPropertiesExpression EntityProperties = new MetadataPropertiesExpression()
{
 AllProperties = false
};
EntityProperties.PropertyNames.AddRange(new string[] { "Attributes" });

'A properties expression to limit the properties to be included with entities
Dim EntityProperties As New MetadataPropertiesExpression() With {.AllProperties = False}
EntityProperties.PropertyNames.AddRange(New String() { "Attributes" })

특성 메타데이터 검색

EntityQueryExpression.AttributeQuery 속성은 EntityQueryExpressionCriteriaProperties와 일치하는 엔터티에 대해 반환되는 특성에 대해 CriteriaProperties를 정의하는 AttributeQueryExpression을 허용합니다.

다음 표에는 MetadataFilterExpression에서 사용할 수 없는 AttributeMetadata 속성이 나와 있습니다.

Description

DisplayName

OptionSet

Targets

다음 예제는 OptionSet이 있는 항목에만 반환되는 특성을 제한하고, 해당 특성에 대해 OptionSetAttributeType 속성만 반환합니다.


//A condition expresson to return optionset attributes
MetadataConditionExpression[] optionsetAttributeTypes = new MetadataConditionExpression[] { 
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.Picklist),
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.State),
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.Status),
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.Boolean)
};

//A filter expression to apply the optionsetAttributeTypes condition expression
MetadataFilterExpression AttributeFilter = new MetadataFilterExpression(LogicalOperator.Or);
AttributeFilter.Conditions.AddRange(optionsetAttributeTypes);

//A Properties expression to limit the properties to be included with attributes
MetadataPropertiesExpression AttributeProperties = new MetadataPropertiesExpression() { AllProperties = false };
AttributeProperties.PropertyNames.Add("OptionSet");
AttributeProperties.PropertyNames.Add("AttributeType");

'A condition expresson to return optionset attributes
                  Dim optionsetAttributeTypes() As MetadataConditionExpression =
                      {
                          New MetadataConditionExpression("AttributeType",
                                                          MetadataConditionOperator.Equals,
                                                          AttributeTypeCode.Picklist),
                          New MetadataConditionExpression("AttributeType",
                                                          MetadataConditionOperator.Equals,
                                                          AttributeTypeCode.State),
                          New MetadataConditionExpression("AttributeType",
                                                          MetadataConditionOperator.Equals,
                                                          AttributeTypeCode.Status),
                          New MetadataConditionExpression("AttributeType",
                                                          MetadataConditionOperator.Equals,
                                                          AttributeTypeCode.Boolean)
                      }

'A filter expression to apply the optionsetAttributeTypes condition expression
Dim AttributeFilter As New MetadataFilterExpression(LogicalOperator.Or)
AttributeFilter.Conditions.AddRange(optionsetAttributeTypes)

'A Properties expression to limit the properties to be included with attributes
Dim AttributeProperties As New MetadataPropertiesExpression() With {.AllProperties = False}
AttributeProperties.PropertyNames.Add("OptionSet")
AttributeProperties.PropertyNames.Add("AttributeType")

관계 메타데이터 검색

EntityQueryExpression.RelationshipQuery 속성은 EntityQueryExpressionCriteriaProperties와 일치하는 엔터티에 대해 필요한 엔터티 관계 CriteriaProperties를 지정하는 RelationshipQueryExpression을 허용합니다.

조건에 RelationshipType 속성을 사용하여 ManyToMany 관계를 반환할지 아니면 OneToMany 관계를 반환할지 지정합니다.

다음 표에는 MetadataFilterExpression에서 사용할 수 없는 관계 메타데이터 속성이 나와 있습니다.

OneToManyRelationshipMetadata.AssociatedMenuConfiguration

OneToManyRelationshipMetadata.CascadeConfiguration

ManyToManyRelationshipMetadata.Entity1AssociatedMenuConfiguration

ManyToManyRelationshipMetadata.Entity2AssociatedMenuConfiguration

레이블 검색

마지막으로 EntityQueryExpression.LabelQuery 속성은 반환할 지역화된 레이블을 결정하는 하나 이상의 정수 LCID 값을 지정할 수 있는 LabelQueryExpression을 허용합니다.유효한 로캘 ID 값은 LCID(로캘 ID) 차트에서 확인할 수 있습니다. 조직에 많은 언어 팩이 설치되어 있으면 모든 언어의 레이블이 반환되고, 그렇지 않으면 LabelQuery를 지정합니다.

다음 예제에서는 사용자 기본 설정 언어만 나타내도록 레이블을 제한하는 LabelQueryExpression을 정의합니다.


private Guid _userId;
private int _languageCode;

_userId = ((WhoAmIResponse)_service.Execute(new WhoAmIRequest())).UserId;
_languageCode = RetrieveUserUILanguageCode(_userId);

protected int RetrieveUserUILanguageCode(Guid userId)
{
 QueryExpression userSettingsQuery = new QueryExpression("usersettings");
 userSettingsQuery.ColumnSet.AddColumns("uilanguageid", "systemuserid");
 userSettingsQuery.Criteria.AddCondition("systemuserid", ConditionOperator.Equal, userId);
 EntityCollection userSettings = _service.RetrieveMultiple(userSettingsQuery);
 if (userSettings.Entities.Count > 0)
 {
  return (int)userSettings.Entities[0]["uilanguageid"];
 }
 return 0;
}


//A label query expression to limit the labels returned to only those for the user's preferred language
LabelQueryExpression labelQuery = new LabelQueryExpression();
labelQuery.FilterLanguages.Add(_languageCode);

Private _userId As Guid
Private _languageCode As Integer
_userId = (CType(_service.Execute(New WhoAmIRequest()), WhoAmIResponse)).UserId
_languageCode = RetrieveUserUILanguageCode(_userId)
 Protected Function RetrieveUserUILanguageCode(ByVal userId As Guid) As Integer
  Dim userSettingsQuery As New QueryExpression("usersettings")
  userSettingsQuery.ColumnSet.AddColumns("uilanguageid", "systemuserid")
  userSettingsQuery.Criteria.AddCondition("systemuserid", ConditionOperator.Equal, userId)
  Dim userSettings As EntityCollection = _service.RetrieveMultiple(userSettingsQuery)
  If userSettings.Entities.Count > 0 Then
Return CInt(Fix(userSettings.Entities(0)("uilanguageid")))
  End If
  Return 0
 End Function
'A label query expression to limit the labels returned to only those for the user's preferred language
Dim labelQuery As New LabelQueryExpression()
labelQuery.FilterLanguages.Add(_languageCode)

새 메타데이터 또는 변경된 메타데이터 검색

RetrieveMetadataChangesResponse 클래스는 요청된 데이터가 들어 있는 강력한 유형의 EntityMetadataCollection을 반환합니다.RetrieveMetadataChangesResponse 클래스는 이후 요청에서RetrieveMetadataChangesRequest.ClientVersionStamp 속성에 전달할 수 있는 ServerVersionStamp 값도 제공합니다. 값이 ClientVersionStamp 속성에 포함되어 있으면 EntityQueryExpression과 일치하고 ClientVersionStamp를 검색한 후 변경된 데이터만 반환됩니다. 유일한 예외는 EntityQueryExpression.PropertiesEntityMetadata.Privileges가 포함되어 있을 경우입니다. 권한은 ClientVersionStamp와 관계 없이 항상 반환됩니다. 이런 방식으로 응용 프로그램은 마지막으로 메타데이터를 쿼리한 이후 관심을 가져야 할 중요한 변경이 발생했는지 여부를 결정할 수 있습니다. 그런 다음 응용 프로그램에서 필요 없는 메타데이터를 다운로드하는 성능 문제를 방지할 수 있도록 새 메타데이터 또는 변경된 메타데이터를 영구 메타데이터 캐시에 병합할 수 있습니다.

HasChanged 속성은 메타데이터 항목에서 변경된 하위 요소를 검색하는 방법을 제공합니다. 모든 메타데이터는 상위 메타데이터 항목의 일부를 반환되므로 OptionMetadata의 레이블이 변경되면 상위 EntityMetadata, AttributeMetadataOptionSetMetadata 속성이 반환됩니다. 하지만 해당 상위 메타데이터 항목에 대해 HasChanged 속성은 false가 됩니다.OptionMetadata.HasChanged 속성만 true가 됩니다.

다음 예제에서는 EntityQueryExpression을 정의하고 null로 설정된 ClientVersionStamp를 실행하여 초기 요청을 만듭니다.


//An entity query expression to combine the filter expressions and property expressions for the query.
EntityQueryExpression entityQueryExpression = new EntityQueryExpression()
{

 Criteria = EntityFilter,
 Properties = EntityProperties,
 AttributeQuery = new AttributeQueryExpression()
 {
  Criteria = AttributeFilter,
  Properties = AttributeProperties
 },
 LabelQuery = labelQuery

};

//Retrieve the metadata for the query without a ClientVersionStamp
RetrieveMetadataChangesResponse initialRequest = getMetadataChanges(entityQueryExpression, null, DeletedMetadataFilters.OptionSet);

protected RetrieveMetadataChangesResponse getMetadataChanges(
 EntityQueryExpression entityQueryExpression,
 String clientVersionStamp,
 DeletedMetadataFilters deletedMetadataFilter)
{
 RetrieveMetadataChangesRequest retrieveMetadataChangesRequest = new RetrieveMetadataChangesRequest()
 {
  Query = entityQueryExpression,
  ClientVersionStamp = clientVersionStamp,
  DeletedMetadataFilters = deletedMetadataFilter
 };

 return (RetrieveMetadataChangesResponse)_service.Execute(retrieveMetadataChangesRequest);

}

'An entity query expression to combine the filter expressions and property expressions for the query.
                  Dim entityQueryExpression_Renamed As New EntityQueryExpression() With
                      {
                          .Criteria = EntityFilter,
                          .Properties = EntityProperties,
                          .AttributeQuery = New AttributeQueryExpression() With
                                            {
                                                .Criteria = AttributeFilter,
                                                .Properties = AttributeProperties
                                            },
                          .LabelQuery = labelQuery
                      }

'Retrieve the metadata for the query without a ClientVersionStamp
                  Dim initialRequest As RetrieveMetadataChangesResponse =
                      getMetadataChanges(entityQueryExpression_Renamed, Nothing, DeletedMetadataFilters.OptionSet)
Protected Function getMetadataChanges(ByVal entityQueryExpression_Renamed As EntityQueryExpression,
                                      ByVal clientVersionStamp As String,
                                      ByVal deletedMetadataFilter As DeletedMetadataFilters) As RetrieveMetadataChangesResponse
    Dim retrieveMetadataChangesRequest_Renamed As New RetrieveMetadataChangesRequest() With
        {
            .Query = entityQueryExpression_Renamed,
            .ClientVersionStamp = clientVersionStamp,
            .DeletedMetadataFilters = deletedMetadataFilter
        }

    Return CType(_service.Execute(retrieveMetadataChangesRequest_Renamed), RetrieveMetadataChangesResponse)

End Function

삭제된 메타데이터에 대한 정보 검색

RetrieveMetadataChangesResponse.DeletedMetadata 속성은 ClientVersionStampDeletedMetadataFilters 속성이 RetrieveMetadataChangesRequest에 설정되어 있으면 DeletedMetadataCollection을 반환합니다.DeletedMetadataCollection에는 시간 제한으로 시스템에서 삭제된 EntityMetadata, AttributeMetadata 또는 RelationshipMetadataBase 개체의 MetadataId 값이 포함됩니다. 자세한 내용은 삭제된 메타데이터 만료을 참조하십시오.

RetrieveMetadataChangesRequest.DeletedMetadataFilters를 사용하여 관심 있는 메타데이터 유형에만 정보를 제한하는 DeletedMetadataFilters 열거형을 사용합니다. 목록은DeletedMetadataFilters 다음 옵션을 제공합니다.

RetrieveMetadataChangesResponse.DeletedMetadata 속성에 있는 GUID 값을 필터링하는 DeletedMetadataFilters 열거형도 RetrieveMetadataChangesResponse.DeletedMetadata에 대한 키로 사용합니다.

메타데이터 캐시를 디자인할 때 삭제한 메타데이터 항목을 식별하고 제거할 수 있도록 각 항목에 대해 MetadataId를 사용하는 것이 좋습니다.

삭제된 메타데이터 만료

삭제되는 메타데이터 항목은 Organization.ExpireSubscriptionsInDays 값으로 지정한 일정 시간 동안 추적됩니다. 기본적으로 이 값은 90일입니다.RetrieveMetadataChangesRequest.ClientVersionStamp 값이 만료일 이전에 마지막 메타데이터 쿼리를 가져온 것임을 나타내면 서비스에서 ExpiredVersionStamp 오류가 발생합니다(0x80044352). 새로 고칠 데이터와 기존 메타데이터 캐시를 검색할 경우 항상 이 오류를 찾아내고 ClientVersionStamp 없이 전달된 두 번째 요청의 결과와 함께 메타데이터 캐시를 다시 초기화할 준비를 해야 합니다. 삭제된 메타데이터를 정확히 추적하는 데 영향을 줄 수 있는 ExpireSubscriptionsInDays 값 변경과 같이 서버의 값이 변경되면 ExpiredVersionStamp 오류도 발생합니다.

다음 예제에서는 ClientVersionStamp를 전달하고 ExpiredVersionStamp를 찾아냅니다. 오류를 찾아내면 ClientVersionStampnull로 설정하여 새 요청에서 전달하여 캐시가 다시 초기화됩니다.


protected String updateOptionLabelList(EntityQueryExpression entityQueryExpression, String clientVersionStamp)
{
 //Retrieve metadata changes and add them to the cache
 RetrieveMetadataChangesResponse updateResponse;
 try
 {
  updateResponse = getMetadataChanges(entityQueryExpression, clientVersionStamp, DeletedMetadataFilters.OptionSet);
  addOptionLabelsToCache(updateResponse.EntityMetadata, true);
  removeOptionLabelsFromCache(updateResponse.DeletedMetadata, true);

 }
 catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> ex)
 {
  // Check for ErrorCodes.ExpiredVersionStamp (0x80044352)
  // Will occur when the timestamp exceeds the Organization.ExpireSubscriptionsInDays value, which is 90 by default.
  if (ex.Detail.ErrorCode == unchecked((int)0x80044352))
  {
   //reinitialize cache
   _optionLabelList.Clear();

   updateResponse = getMetadataChanges(entityQueryExpression, null, DeletedMetadataFilters.OptionSet);
   //Add them to the cache and display the changes
   addOptionLabelsToCache(updateResponse.EntityMetadata, true);

  }
  else
  {
   throw ex;
  }

 }
 return updateResponse.ServerVersionStamp;
}

Protected Function updateOptionLabelList(ByVal entityQueryExpression_Renamed As EntityQueryExpression,
                                         ByVal clientVersionStamp As String) As String
    'Retrieve metadata changes and add them to the cache
    Dim updateResponse As RetrieveMetadataChangesResponse
    Try
        updateResponse = getMetadataChanges(entityQueryExpression_Renamed, clientVersionStamp, DeletedMetadataFilters.OptionSet)
        addOptionLabelsToCache(updateResponse.EntityMetadata, True)
        removeOptionLabelsFromCache(updateResponse.DeletedMetadata, True)

    Catch ex As FaultException(Of Microsoft.Xrm.Sdk.OrganizationServiceFault)
        ' Check for ErrorCodes.ExpiredVersionStamp (0x80044352)
        ' Will occur when the timestamp exceeds the Organization.ExpireSubscriptionsInDays value, which is 90 by default.
        'INSTANT VB TODO TASK: There is no VB equivalent to 'unchecked' in this context:
        If ex.Detail.ErrorCode = CInt(&amp;H80044352) Then
            'reinitialize cache
            _optionLabelList.Clear()

            updateResponse = getMetadataChanges(entityQueryExpression_Renamed, Nothing, DeletedMetadataFilters.OptionSet)
            'Add them to the cache and display the changes
            addOptionLabelsToCache(updateResponse.EntityMetadata, True)

        Else
            Throw ex
        End If

    End Try
    Return updateResponse.ServerVersionStamp
End Function

삭제된 메타데이터를 검색할 때의 성능

메타데이터 항목이 삭제되면 Microsoft Dynamics 365 메타데이터 캐시가 아니라 데이터베이스에 저장됩니다. 삭제된 메타데이터가 단지 MetadataId 및 메타데이터 항목 유형으로 제한되지만 데이터베이스 액세스는 변경 내용을 쿼리하는 것보다 많은 서버 리소스가 필요한 작업입니다.

참고 항목

서버에서 Microsoft Dynamics 365 확장
Microsoft Dynamics 365 서비스 오프라인 사용
샘플: 쿼리 메타데이터 및 변경 검색
Dynamics 365 메타데이터에서 조직 서비스 사용
Customize 엔터티 메타데이터
Customize 특성 메타데이터 메시지
엔터티 관계 메타데이터 사용자 지정
JavaScript를 사용하여 메타데이터 쿼리

Microsoft Dynamics 365

© 2017 Microsoft. All rights reserved. 저작권 정보