Pages

Monday, November 17, 2014

Convert Org Owned Entity to User Owned

A while back I discussed the pros and cons of user vs. organization owned entities. I concluded as follows:

The theory might all be well and good, but let's say you're presently in the predicament described above i.e. you're in production and have come across a requirement that means that you'll need to convert an entity from organization-owned to user-owned - what are the steps to achieve this? In the next post I'll attempt to address this with a step by step walk through.
Well it's about time I made good on that promise... So here goes -

Caution: This is not for the fainthearted. Especially in CRM Online installations where you can't really make a backup (as concluded in the above referenced post - when in doubt go with user-owned entities...).

Step 1 - Export all the data

You need to save all your data linked to the entity you wish to update. Assuming this is a CRM Online instance you can use the export to Excel option (in on-premise there are of course other options). This includes (but not necessarily limited to) the following:

  • Export Main  Entity




  • Export Notes - All columns
  • Export Activities - All columns
  • Export data from other 1:N relationships that you wish to recreate/relate

You need to resign your self to the fact that you will lose information stored in system attributes such as created/modified by/on.

Generally speaking, restoring N:1 relationships is not a problem because they'll be recreated with the re-import.

However with the 1:N relationship as in the case of notes and activities there is a level of effort involved so you'll need to make a judgment call of whether it is worth it. Same applies for N:N relationships (perhaps even more so since there is no way to re-import using native tools. Bottom line if there is a lot of dependent data this exercise is likely going to be too painful and you'll need to consider other options such as duplicating the entity and migrating the data over with all the relationships (tools such as Scribe can help here).



Step 2 - Create and Export Solution


Retains all customizations - views, forms etc.

  • Export a solution containing the entity you wish to modify and workflows on that entity 
  • Export a solution with everything but entity (including workflows, security roles)....
  • Make a copy of the exported zip
  • Unzip the solution, and open customizations.xml in a text editor
  • Replace the following section... 
<attribute PhysicalName="OrganizationId">
              <Type>lookup</Type>
              <Name>organizationid</Name>
              <LogicalName>organizationid</LogicalName>
              <RequiredLevel>none</RequiredLevel>
              <ImeMode>auto</ImeMode>
              <ValidForReadApi>1</ValidForReadApi>
              <IsCustomField>0</IsCustomField>
              <IsAuditEnabled>1</IsAuditEnabled>
              <IsSecured>0</IsSecured>
              <IntroducedVersion>1.0</IntroducedVersion>
              <IsCustomizable>1</IsCustomizable>
              <IsRenameable>1</IsRenameable>
              <CanModifySearchSettings>1</CanModifySearchSettings>
              <CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
              <CanModifyAdditionalSettings>1</CanModifyAdditionalSettings>
              <ReferencedEntityObjectTypeCode>1019</ReferencedEntityObjectTypeCode>
              <LookupTypes />
              <displaynames>
                <displayname description="Organization Id" languagecode="1033" />
              </displaynames>
              <Descriptions>
                <Description description="Unique identifier for the organization" languagecode="1033" />
              </Descriptions>
            </attribute>
              
  • With:
<attribute PhysicalName="OwnerId">
              <Type>owner</Type>
              <Name>ownerid</Name>
              <LogicalName>ownerid</LogicalName>
              <RequiredLevel>systemrequired</RequiredLevel>
              <DisplayMask>ValidForAdvancedFind|ValidForForm|ValidForGrid|RequiredForForm</DisplayMask>
              <ImeMode>auto</ImeMode>
              <ValidForReadApi>1</ValidForReadApi>
              <ValidForCreateApi>1</ValidForCreateApi>
              <IsCustomField>0</IsCustomField>
              <IsAuditEnabled>1</IsAuditEnabled>
              <IsSecured>0</IsSecured>
              <IntroducedVersion>1.0.0.0</IntroducedVersion>
              <IsCustomizable>1</IsCustomizable>
              <IsRenameable>1</IsRenameable>
              <CanModifySearchSettings>1</CanModifySearchSettings>
              <CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
              <CanModifyAdditionalSettings>1</CanModifyAdditionalSettings>
              <LookupStyle>single</LookupStyle>
              <LookupTypes>
                <LookupType id="00000000-0000-0000-0000-000000000000">8</LookupType>
                <LookupType id="00000000-0000-0000-0000-000000000000">9</LookupType>
              </LookupTypes>
              <displaynames>
                <displayname description="Owner" languagecode="1033" />
              </displaynames>
              <Descriptions>
                <Description description="Owner Id" languagecode="1033" />
              </Descriptions>
            </attribute>
            <attribute PhysicalName="OwnerIdName">
              <Type>nvarchar</Type>
              <Name>owneridname</Name>
              <LogicalName>owneridname</LogicalName>
              <RequiredLevel>systemrequired</RequiredLevel>
              <ImeMode>auto</ImeMode>
              <ValidForReadApi>1</ValidForReadApi>
              <IsCustomField>0</IsCustomField>
              <IsAuditEnabled>0</IsAuditEnabled>
              <IsLogical>1</IsLogical>
              <IsSecured>0</IsSecured>
              <IntroducedVersion>1.0.0.0</IntroducedVersion>
              <IsCustomizable>1</IsCustomizable>
              <IsRenameable>1</IsRenameable>
              <CanModifySearchSettings>1</CanModifySearchSettings>
              <CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
              <CanModifyAdditionalSettings>1</CanModifyAdditionalSettings>
              <Format>text</Format>
              <MaxLength>100</MaxLength>
              <Length>320</Length>
              <Descriptions>
                <Description description="Name of the owner" languagecode="1033" />
              </Descriptions>
            </attribute>
            <attribute PhysicalName="OwnerIdType">
              <Type>int</Type>
              <Name>owneridtype</Name>
              <LogicalName>owneridtype</LogicalName>
              <RequiredLevel>systemrequired</RequiredLevel>
              <DisplayMask>ObjectTypeCode</DisplayMask>
              <ImeMode>disabled</ImeMode>
              <ValidForReadApi>1</ValidForReadApi>
              <ValidForCreateApi>1</ValidForCreateApi>
              <IsCustomField>0</IsCustomField>
              <IsAuditEnabled>1</IsAuditEnabled>
              <IsSecured>0</IsSecured>
              <IntroducedVersion>1.0.0.0</IntroducedVersion>
              <IsCustomizable>1</IsCustomizable>
              <IsRenameable>1</IsRenameable>
              <CanModifySearchSettings>1</CanModifySearchSettings>
              <CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
              <CanModifyAdditionalSettings>1</CanModifyAdditionalSettings>
              <Format></Format>
              <MinValue>-2147483648</MinValue>
              <MaxValue>2147483647</MaxValue>
              <Descriptions>
                <Description description="Owner Id Type" languagecode="1033" />
              </Descriptions>
            </attribute>
            <attribute PhysicalName="OwnerIdYomiName">
              <Type>nvarchar</Type>
              <Name>owneridyominame</Name>
              <LogicalName>owneridyominame</LogicalName>
              <RequiredLevel>systemrequired</RequiredLevel>
              <ImeMode>auto</ImeMode>
              <ValidForReadApi>1</ValidForReadApi>
              <IsCustomField>0</IsCustomField>
              <IsAuditEnabled>0</IsAuditEnabled>
              <IsLogical>1</IsLogical>
              <IsSecured>0</IsSecured>
              <IntroducedVersion>1.0.0.0</IntroducedVersion>
              <IsCustomizable>1</IsCustomizable>
              <IsRenameable>1</IsRenameable>
              <CanModifySearchSettings>1</CanModifySearchSettings>
              <CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
              <CanModifyAdditionalSettings>1</CanModifyAdditionalSettings>
              <Format>text</Format>
              <MaxLength>100</MaxLength>
              <Length>320</Length>
              <YomiOf>OwnerIdName</YomiOf>
              <Descriptions>
                <Description description="Yomi name of the owner" languagecode="1033" />
              </Descriptions>
            </attribute>
            <attribute PhysicalName="OwningBusinessUnit">
              <Type>lookup</Type>
              <Name>owningbusinessunit</Name>
              <LogicalName>owningbusinessunit</LogicalName>
              <RequiredLevel>none</RequiredLevel>
              <ImeMode>auto</ImeMode>
              <ValidForReadApi>1</ValidForReadApi>
              <IsCustomField>0</IsCustomField>
              <IsAuditEnabled>0</IsAuditEnabled>
              <IsSecured>0</IsSecured>
              <IntroducedVersion>1.0.0.0</IntroducedVersion>
              <IsCustomizable>1</IsCustomizable>
              <IsRenameable>1</IsRenameable>
              <CanModifySearchSettings>1</CanModifySearchSettings>
              <CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
              <CanModifyAdditionalSettings>1</CanModifyAdditionalSettings>
              <ReferencedEntityObjectTypeCode>10</ReferencedEntityObjectTypeCode>
              <LookupStyle>single</LookupStyle>
              <LookupTypes />
              <displaynames>
                <displayname description="Owning Business Unit" languagecode="1033" />
              </displaynames>
              <Descriptions>
                <Description description="Unique identifier for the business unit that owns the record" languagecode="1033" />
              </Descriptions>
            </attribute>


  • Replace the following...
<OwnershipTypeMask>UserOwned</OwnershipTypeMask>
  • With:
<OwnershipTypeMask>UserOwned</OwnershipTypeMask>

  • Replace the following section (be sure to update "your_entity" with the name of your entity)...
<EntityRelationship Name="organization_your_entity">
      <EntityRelationshipType>OneToMany</EntityRelationshipType>
      <IsCustomizable>1</IsCustomizable>
      <IntroducedVersion>1.0</IntroducedVersion>
      <ReferencingEntityName>your_entity</ReferencingEntityName>
      <ReferencedEntityName>Organization</ReferencedEntityName>
      <CascadeAssign>NoCascade</CascadeAssign>
      <CascadeDelete>NoCascade</CascadeDelete>
      <CascadeReparent>NoCascade</CascadeReparent>
      <CascadeShare>NoCascade</CascadeShare>
      <CascadeUnshare>NoCascade</CascadeUnshare>
      <ReferencingAttributeName>OrganizationId</ReferencingAttributeName>
      <RelationshipDescription>
        <Descriptions>
          <Description description="Unique identifier for the organization" languagecode="1033" />
        </Descriptions>
      </RelationshipDescription>
      <field name="organizationid" requiredlevel="none" imemode="auto">
        <IsCustomizable>1</IsCustomizable>
        <IsRenameable>1</IsRenameable>
        <CanModifySearchSettings>1</CanModifySearchSettings>
        <CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
        <IsSecured>0</IsSecured>
        <IsAuditEnabled>1</IsAuditEnabled>
        <displaynames>
          <displayname description="Organization Id" languagecode="1033" />
        </displaynames>
      </field>
    </EntityRelationship>

  • With:
    <EntityRelationship Name="owner_your_entity">
      <EntityRelationshipType>OneToMany</EntityRelationshipType>
      <IsCustomizable>1</IsCustomizable>
      <IntroducedVersion>1.0.0.0</IntroducedVersion>
      <ReferencingEntityName>your_entity</ReferencingEntityName>
      <ReferencedEntityName>Owner</ReferencedEntityName>
      <CascadeAssign>NoCascade</CascadeAssign>
      <CascadeDelete>NoCascade</CascadeDelete>
      <CascadeReparent>NoCascade</CascadeReparent>
      <CascadeShare>NoCascade</CascadeShare>
      <CascadeUnshare>NoCascade</CascadeUnshare>
      <ReferencingAttributeName>OwnerId</ReferencingAttributeName>
      <RelationshipDescription>
        <Descriptions>
          <Description description="Owner Id" languagecode="1033" />
        </Descriptions>
      </RelationshipDescription>
      <field name="ownerid" requiredlevel="systemrequired" imemode="auto" lookupstyle="single" lookupbrowse="0" lookuptypes="8, 9">
        <IsCustomizable>1</IsCustomizable>
        <IsRenameable>1</IsRenameable>
        <CanModifySearchSettings>1</CanModifySearchSettings>
        <CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
        <IsSecured>0</IsSecured>
        <DisplayMask>ValidForAdvancedFind|ValidForForm|ValidForGrid|RequiredForForm</DisplayMask>
        <IsAuditEnabled>1</IsAuditEnabled>
        <displaynames>
          <displayname description="Owner" languagecode="1033" />
        </displaynames>
      </field>
    </EntityRelationship>
    <EntityRelationship Name="team_your_entity">
      <EntityRelationshipType>OneToMany</EntityRelationshipType>
      <IsCustomizable>1</IsCustomizable>
      <IntroducedVersion>1.0.0.0</IntroducedVersion>
      <ReferencingEntityName>your_entity</ReferencingEntityName>
      <ReferencedEntityName>Team</ReferencedEntityName>
      <CascadeAssign>NoCascade</CascadeAssign>
      <CascadeDelete>NoCascade</CascadeDelete>
      <CascadeReparent>NoCascade</CascadeReparent>
      <CascadeShare>NoCascade</CascadeShare>
      <CascadeUnshare>NoCascade</CascadeUnshare>
      <ReferencingAttributeName>OwningTeam</ReferencingAttributeName>
      <RelationshipDescription>
        <Descriptions>
          <Description description="Unique identifier for the team that owns the record." languagecode="1033" />
        </Descriptions>
      </RelationshipDescription>
      <field name="owningteam" requiredlevel="none" imemode="auto" lookupstyle="single" lookupbrowse="0">
        <IsCustomizable>1</IsCustomizable>
        <IsRenameable>1</IsRenameable>
        <CanModifySearchSettings>1</CanModifySearchSettings>
        <CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
        <IsSecured>0</IsSecured>
        <IsAuditEnabled>0</IsAuditEnabled>
        <displaynames>
          <displayname description="Owning Team" languagecode="1033" />
        </displaynames>
      </field>
    </EntityRelationship>
    <EntityRelationship Name="user_your_entity">
      <EntityRelationshipType>OneToMany</EntityRelationshipType>
      <IsCustomizable>1</IsCustomizable>
      <IntroducedVersion>1.0.0.0</IntroducedVersion>
      <ReferencingEntityName>your_entity</ReferencingEntityName>
      <ReferencedEntityName>SystemUser</ReferencedEntityName>
      <CascadeAssign>NoCascade</CascadeAssign>
      <CascadeDelete>NoCascade</CascadeDelete>
      <CascadeReparent>NoCascade</CascadeReparent>
      <CascadeShare>NoCascade</CascadeShare>
      <CascadeUnshare>NoCascade</CascadeUnshare>
      <ReferencingAttributeName>OwningUser</ReferencingAttributeName>
      <RelationshipDescription>
        <Descriptions>
          <Description description="Unique identifier for the user that owns the record." languagecode="1033" />
        </Descriptions>
      </RelationshipDescription>
      <field name="owninguser" requiredlevel="none" imemode="auto" lookupstyle="single" lookupbrowse="0">
        <IsCustomizable>1</IsCustomizable>
        <IsRenameable>1</IsRenameable>
        <CanModifySearchSettings>1</CanModifySearchSettings>
        <CanModifyRequirementLevelSettings>1</CanModifyRequirementLevelSettings>
        <IsSecured>0</IsSecured>
        <IsAuditEnabled>0</IsAuditEnabled>
        <displaynames>
          <displayname description="Owning User" languagecode="1033" />
        </displaynames>
      </field>
    </EntityRelationship>
  • Finally, update your entity name so it can exist side by side (temporarily) with the entity you will be replace. For example, find and replace all your_entity with your_entity2.
  • Similarly, replace the entity description with a replacement value so you'll be able to distinguish from the front end.
      <Name LocalizedName="Your Entity2" OriginalName="Your Entity2">snt_Your Entity2</Name>
      <ObjectTypeCode>10016</ObjectTypeCode>
      <EntityInfo>
        <entity Name="your_entity2">
          <LocalizedNames>
            <LocalizedName description="Your Entity2" languagecode="1033" />
          </LocalizedNames>
          <LocalizedCollectionNames>
            <LocalizedCollectionName description="Your Entity 2" languagecode="1033" />

  • Save Customization.xml and copy back into exported zip

Step 3 - Import Customization

  • Import modified zip file to recreate entity
  • Import other solution file created
  • Verify forms, views etc.
  • Verify entity is user-owne
Note: If you get an invalid reference error when importing you'll need to remove the reference (could be a sub-grid or jscript web resource reference) and you'll need to manually add back after the import.

Step 4 - Import Data

Use the data import wizard to re-import the data to your new duplicated entity.


Step 5 - Post Steps

Once you're satisfied with the state of affairs of your new entity you can apply the post steps which includes:

  • Delete old entity - This can get quite hairy. Deleting an entity requires removing all kinds of dependencies. Make sure you export entities, workflows, security roles etc. and keep careful manual track of any thing that needs to be manually reset

  • Update forms - you may need to update the forms with removed references that caused import customization errors. 
  • Update security roles
  • Update workflow

No comments:

Post a Comment