z. Creating Rock Migrations - SparkDevNetwork/Rock GitHub Wiki

Dear Core Team,

There are some complexities with managing EF migrations in a multi-developer environment. In fact, you really have to avoid having a situation where multiple developers have created overlapping (or parallel) migrations. We've found it's best to use the following high-level strategy for adding migrations to source control:

  • Pull latest develop branch and make sure you've run the latest migrations
  • If needed, merge your develop into your feature branch.
  • Claim the Migration Token (core team internal use only)
  • Create a new migration for your branch and test, test, test (up and down).
  • If needed, merge your feature branch to the develop branch.
  • Push your develop branch to origin.

You should wait util your code is ready to commit to the develop branch before you build a migration. Once your migration is pushed it's essentially going to include it into everyone else's development environment/database. You better get it right ;) ...but if you don't, see the section below on how to undo the trouble you might have created.

Review and use the following checklists.

High Level Steps When Making Model Changes

  1. Add to the Model and compile
  2. Claim the Migration Token (core team internal use only)
  3. Add-Migration AddExampleNewPropertyToSomeModel (for example)
  4. Update-Database
  5. Run the Rock.CodeGeneration tool
  6. Commit/push if stable or finish next step if needed before commit/push.
  7. Then whatever UI blocks, etc need to be updated to take advantage of the new change or feature

Create the new migration class

  1. Run any dev tools such as Dev Tools\Sql\CodeGen_PagesBlocksAttributesMigration.sql script. It will output stuff you'll want to use in your next step.
  2. Run Add-Migration [YOUR_MIGRATION_NAME]
  3. Edit this skeleton migration and paste in the stuff from the MigrationUp output into your migration's Up() method and then the MigrationDown output into the Down() method. Pay particular attention to the order that things are deleted since you cannot delete many things unless any related items are first deleted.
  4. REVIEW each item you just pasted. Not all of them will be things you should include in your migration.
  5. Manually add any other data items that were not already accounted for by the SQL script including:
  • EntityTypes
  • NoteTypes
  • PageContext (if any of your blocks use Context you should double-check this one)
  • Global Attributes

Verify Your Assumptions

You MUST double check your SQL looking for possible problems with your assumptions. Use the following checklist to help you verify your SQL:

  1. Include GOOD comments. Tell us what you're doing!
  2. Never use an ID always use a GUID. If you need an ID go fetch it using a GUID.
  3. SELECT TOP(1) instead of assuming there is only one
  4. Explicitly add any needed attributes for your new block types. DON'T rely on the system to add them for you.

Important: You should consider a few things when you're creating your Up() and Down() migration. For example, if your migration adds a new NoteType be aware that there could be Note records using it. Those notes are things you did not create and it might be problematic if you destroyed that data. Similarly, if you could not delete it during a Down() then you probably should check if it exists already during the Up(). Therefore you may want to do something like this in the Up():

    public override void Up()
    {
        Sql( @"
            -- Add 'Prayer Comment' NoteType if it's not already there
            DECLARE @PrayerCommentNoteTypeId int
            SELECT @PrayerCommentNoteTypeId = [Id] FROM [NoteType] WHERE [Guid] = '0EBABD75-0890-4756-A9EE-62626282BB5D'
            IF @PrayerCommentNoteTypeId IS NULL
            BEGIN
            INSERT INTO [NoteType] ...
                    ...
             ");
        // ...
    }

... and this in the Down():

    public override void Down()
    {
        Sql( @"
            -- Delete the NoteType but ONLY if it's not being used...
            IF NOT EXISTS(SELECT * FROM  [Note] WHERE [NoteTypeId] IN 
                (SELECT [Id] FROM [NoteType] WHERE [Guid] = '0EBABD75-0890-4756-A9EE-62626282BB5D' )
            )
            BEGIN
                DELETE [NoteType] WHERE [Guid] = '0EBABD75-0890-4756-A9EE-62626282BB5D'
            END
             ");

            // ...
    }

Note: You can use the methods listed in the Migration Helper Methods section below.

###Regarding quotes in migrations Be sure to double-up any quotations that you make within a SQL command. For example, if you were tp want to have a string that said {He said "Rock"}, then you would write it as 'He said ""Rock""'. If working with JSON values within a SQL command, remember to only use double single-quotation marks, as the double double-quotation marks are used to distinguish between JSON keys and values.

Test your new migration class

  1. Replace your db name with a new database name into your RockContext connection string in your web.connectionStrings.config file.
  2. Run Update-Database to see if it worked.
  3. Verify everything by running Rock (F5) and checking every detail of your stuff.
  4. If it's not good, return to step 3 in the previous section; otherwise proceed to next step.
  5. Test your Down() migration by migrating back to the last migration that exists before your new migration. Use the Update-Database -TargetMigration:[THE_PREVIOUS_ONE]. If that was successful, continue.
  6. If applicable, add some data using your new blocks (if any) and re-test your Down() and your Up() migrations. This could shake out a few more assumptions you've made about your migration.
  7. When everything is looking A-OK, proceed to the Commit/Push/Deploy section; otherwise go back to step 3 in the previous section.

NOTE: Never delete your migration before you run a 'Down' migration (targetting the previous migration).

Commit/Push/Deploy

If everything looks good, you can commit your changes, merge into the develop branch (as needed), and push up to origin develop branch.

Trouble During Pull and Rebase

If you run into trouble during a git pull rebase it probably implies that someone else committed a migration before yours. You should consider the following steps to undo/reorder your migration to come after the other new migrations.

  1. Determine if you should ignore (exclude from project) any new migrations that might be in your Rock.csproj file. Resolve conflicts enough to be able to load the Rock project in Visual Studio.
  2. Perform an Update-Database -TargetMigration:[THE_PREVIOUS_ONE] to return to the migration prior to yours.
  3. Make a copy of you migration file (outside of your solution) and delete it.
  4. Re-include any migrations (if you excluded them in step 1) and run Update-Database.
  5. Recreate your migration using the procedure described in the earlier section.
  6. When everything's ready commit and push your changes to Github.

Migration Helper Methods

ActionTypeAttributeValue

Method Description Signature
AddActionTypeAttributeValue Adds the action type attribute value. string actionTypeGuid, string attributeGuid, string value

ActionTypePersonAttributeValue

Method Description Signature
AddActionTypePersonAttributeValue Adds an action type person attribute value. Because there's not way to link to another person in target database, person attribute values are just set to the first person alias record in target database which will most likely be the Admin, Admin record. string actionTypeGuid, string attributeGuid, string value

Attribute

Method Description Signature
DeleteAttribute Deletes the attribute. string guid

AttributeQualifier

Method Description Signature
AddAttributeQualifier Adds the attribute qualifier. string attributeGuid, string key, string value, string guid

AttributeValue

Method Description Signature
AddAttributeValue Adds a new attribute value for the given attributeGuid if it does not already exist. string attributeGuid, int entityId, string value, string guid

BinaryFileType

Method Description Signature
UpdateBinaryFileType Updates the type of the binary file. string storageEntityTypeId, string name, string description, string iconCssClass, string guid, bool allowCaching, bool requiresViewSecurity

Block

Method Description Signature
AddBlock Adds a new Block of the given block type to the given page (optional) and layout (optional), setting its values with the given parameter values. If only the layout is given, edit/configuration authorization will also be inserted into the Auth table for the admin role (GroupId 2). string pageGuid, string layoutGuid, string blockTypeGuid, string name, string zone, string preHtml, string postHtml, int order, string guid
DeleteBlock Deletes the block and any authorization records that belonged to it. string guid

BlockAttribute

Method Description Signature
DeleteBlockAttribute Deletes the block Attribute. string guid

BlockAttributeValue

Method Description Signature
AddBlockAttributeValue Adds a new block attribute value for the given block guid and attribute guid, deleting any previously existing attribute value first. string blockGuid, string attributeGuid, string value, bool appendToExisting
DeleteBlockAttributeValue Deletes the block attribute value. string blockGuid, string attributeGuid

BlockType

Method Description Signature
AddBlockType Adds a new BlockType. string name, string description, string path, string category, string guid
UpdateBlockType Updates the BlockType by path (if it exists); otherwise it inserts a new record. In either case it will be marked IsSystem. string name, string description, string path, string category, string guid
DeleteBlockType Deletes the BlockType. string guid

BlockTypeAttribute

Method Description Signature
AddBlockTypeAttribute Adds a new BlockType Attribute for the given blocktype and key. string blockTypeGuid, string fieldTypeGuid, string name, string key, string category, string description, int order, string defaultValue, string guid, bool isRequired
UpdateBlockTypeAttribute Updates the BlockType Attribute for the given blocktype and key (if it exists); otherwise it inserts a new record. string blockTypeGuid, string fieldTypeGuid, string name, string key, string category, string description, int order, string defaultValue, string guid

Category

Method Description Signature
UpdateCategory Updates the category. string entityTypeGuid, string name, string iconCssClass, string description, string guid, int order
DeleteCategory Deletes the category. string guid

DefinedType

Method Description Signature
AddDefinedType Adds a new DefinedType. string category, string name, string description, string guid, string helpText
DeleteDefinedType Deletes the DefinedType. string guid

DefinedTypeAttribute

Method Description Signature
AddDefinedTypeAttribute Adds the defined type attribute. string definedTypeGuid, string fieldTypeGuid, string name, string key, string description, int order, string defaultValue, string guid

DefinedValue

Method Description Signature
AddDefinedValue Adds a new DefinedValue for the given DefinedType. string definedTypeGuid, string value, string description, string guid, bool isSystem
UpdateDefinedValue Updates (or Adds) the defined value for the given DefinedType. string definedTypeGuid, string value, string description, string guid, bool isSystem
DeleteDefinedValue Deletes the DefinedValue. string guid

DefinedValueAttributeValue

Method Description Signature
AddDefinedValueAttributeValue Adds the defined value attribute value. string definedValueGuid, string attributeGuid, string value
UpdateDefinedValueAttributeValue Adds the defined value attribute value. string definedValueGuid, string attributeGuid, string value

DefinedValueAttributeValueByValue

Method Description Signature
AddDefinedValueAttributeValueByValue Adds the name of the defined value attribute value by. string definedTypeGuid, string definedValueValue, string attributeKey, string value

DefinedValueByValue

Method Description Signature
UpdateDefinedValueByValue Updates the name of the defined value by. string definedTypeGuid, string value, string description, int order, bool isSystem

EntityAttribute

Method Description Signature
AddEntityAttribute Adds a new EntityType Attribute for the given EntityType, FieldType, and name (key). string entityTypeName, string fieldTypeGuid, string entityTypeQualifierColumn, string entityTypeQualifierValue, string name, string category, string description, int order, string defaultValue, string guid
UpdateEntityAttribute Updates the Entity Attribute for the given EntityType, FieldType, and name (key). otherwise it inserts a new record. string entityTypeName, string fieldTypeGuid, string entityTypeQualifierColumn, string entityTypeQualifierValue, string name, string description, int order, string defaultValue, string guid

EntityType

Method Description Signature
UpdateEntityType Updates the EntityType by name (if it exists); otherwise it inserts a new record. string name, string guid, bool isEntity, bool isSecured
UpdateEntityType Updates the EntityType by name (if it exists); otherwise it inserts a new record. string name, string friendlyName, string assemblyName, bool isEntity, bool isSecured, string guid
DeleteEntityType Deletes the EntityType. string guid

EntityTypeMultiValueFieldType

Method Description Signature
UpdateEntityTypeMultiValueFieldType Updates the EntityType MultiValueFieldType string entityTypeName, string fieldTypeGuid

EntityTypeSingleValueFieldType

Method Description Signature
UpdateEntityTypeSingleValueFieldType Updates the EntityType SingleValueFieldType string entityTypeName, string fieldTypeGuid

FieldType

Method Description Signature
UpdateFieldType Updates the FieldType by assembly and className (if it exists); otherwise it inserts a new record. string name, string description, string assembly, string className, string guid, bool IsSystem
DeleteFieldType Deletes the FieldType. string guid

GlobalAttribute

Method Description Signature
AddGlobalAttribute Adds a global Attribute for the given FieldType, entityTypeQualifierColumn, entityTypeQualifierValue and name (key). Note: This method delets the Attribute first if it had already existed. string fieldTypeGuid, string entityTypeQualifierColumn, string entityTypeQualifierValue, string name, string description, int order, string defaultValue, string guid

Group

Method Description Signature
DeleteGroup Deletes the group. string guid, bool orphanAnyChildren

GroupMemberAttributeDefinedValue

Method Description Signature
AddGroupMemberAttributeDefinedValue Adds or updates a group member Attribute for the given group for storing a particular defined value. The defined values are constrained by the given defined type. string groupGuid, string name, string description, int order, string defaultValue, bool isGridColumn, bool isMultiValue, bool isRequired, string definedTypeGuid, string guid, bool isSystem
UpdateGroupMemberAttributeDefinedValue Adds or updates a group member Attribute for the given group for storing a particular defined value. The defined values are constrained by the given defined type. string groupGuid, string name, string description, int order, string defaultValue, bool isGridColumn, bool isMultiValue, bool isRequired, string definedTypeGuid, string guid, bool isSystem

GroupType

Method Description Signature
DeleteGroupType Deletes the GroupType. string guid

GroupTypeGroupAttribute

Method Description Signature
AddGroupTypeGroupAttribute Adds a new GroupType "Group Attribute" for the given GroupType using the given values. string groupTypeGuid, string fieldTypeGuid, string name, string description, int order, string defaultValue, string guid

GroupTypeRole

Method Description Signature
AddGroupTypeRole Adds or Updates the GroupTypeRole for the given guid (if it exists); otherwise it inserts a new record. Can also set the role as the default for the given GroupType if isDefaultGroupTypeRole is set to true. string groupTypeGuid, string name, string description, int order, int? maxCount, int? minCount, string guid, bool isSystem, bool isLeader, bool isDefaultGroupTypeRole
UpdateGroupTypeRole Adds or Updates the GroupTypeRole for the given guid (if it exists); otherwise it inserts a new record. Can also set the role as the default for the given GroupType if isDefaultGroupTypeRole is set to true. string groupTypeGuid, string name, string description, int order, int? maxCount, int? minCount, string guid, bool isSystem, bool isLeader, bool isDefaultGroupTypeRole
DeleteGroupTypeRole Deletes the GroupTypeRole. string guid

HtmlContentBlock

Method Description Signature
UpdateHtmlContentBlock Add or Updates the HTML content for an HTML Content Block string blockGuid, string htmlContent, string guid

Layout

Method Description Signature
AddLayout Adds a new Layout to the given site. string siteGuid, string fileName, string name, string description, string guid
DeleteLayout Deletes the Layout. string guid

Page

Method Description Signature
AddPage Adds a new Page to the given parent page. The new page will be ordered as last child of the parent page. string parentPageGuid, string layoutGuid, string name, string description, string guid, string iconCssClass, string insertAfterPageGuid
MovePage Moves the Page to the new given parent page. string pageGuid, string parentPageGuid
DeletePage Deletes the Page and any PageViews that use the page. string guid

PageContext

Method Description Signature
AddPageContext string pageGuid, string entity, string idParameter
UpdatePageContext Adds or Updates PageContext to the given page, entity, idParameter string pageGuid, string entity, string idParameter, string guid
DeletePageContext Deletes the page context. string guid

PageRoute

Method Description Signature
AddPageRoute Adds a new PageRoute to the given page but only if the given route name does not exist. string pageGuid, string route

PersonAttribute

Method Description Signature
UpdatePersonAttribute Updates the BlockType Attribute for the given blocktype and key (if it exists); otherwise it inserts a new record. string fieldTypeGuid, string categoryGuid, string name, string key, string iconCssClass, string description, int order, string defaultValue, string guid

PersonAttributeCategory

Method Description Signature
UpdatePersonAttributeCategory Updates the person attribute category. string name, string iconCssClass, string description, string guid, int order

PersonBadge

Method Description Signature
UpdatePersonBadge Updates the PersonBadge by Guid (if it exists); otherwise it inserts a new record. string name, string description, string entityTypeName, int order, string guid

PersonBadgeAttribute

Method Description Signature
AddPersonBadgeAttribute Adds (or Deletes and Adds) the person badge attribute. string personBadgeGuid, string fieldTypeGuid, string name, string key, string description, int order, string defaultValue, string guid

PersonBadgeAttributeValue

Method Description Signature
AddPersonBadgeAttributeValue Adds/Updates the person badge attribute value. string personBadgeGuid, string attributeGuid, string value

Report

Method Description Signature
AddReport Adds a report. string categoryGuid, string dataViewGuid, string entityTypeGuid, string name, string description, string guid, int? fetchTop
DeleteReport Deletes the report string guid

ReportField

Method Description Signature
DeleteReportField Deletes the report field. string guid

SecurityAuth

Method Description Signature
AddSecurityAuth Adds the security auth record for the given entity type and group. string entityTypeName, string action, string groupGuid, string authGuid
DeleteSecurityAuth Deletes the security auth record. string guid

SecurityAuthForAttribute

Method Description Signature
AddSecurityAuthForAttribute Adds the attribute security authentication. Set GroupGuid to null when setting to a special role string attributeGuid, int order, string action, bool allow, string groupGuid, int specialRole, string authGuid
DeleteSecurityAuthForAttribute Deletes the security authentication for page. string attributeGuid

SecurityAuthForBinaryFileType

Method Description Signature
AddSecurityAuthForBinaryFileType Adds the binaryfiletype security authentication. Set GroupGuid to null when setting to a special role string binaryFileTypeGuid, int order, string action, bool allow, string groupGuid, Rock.Model.SpecialRole specialRole, string authGuid

SecurityAuthForBlock

Method Description Signature
AddSecurityAuthForBlock Adds the page security authentication. Set GroupGuid to null when setting to a special role string blockGuid, int order, string action, bool allow, string groupGuid, Rock.Model.SpecialRole specialRole, string authGuid
DeleteSecurityAuthForBlock Deletes the security authentication for block. string blockGuid

SecurityAuthForCategory

Method Description Signature
AddSecurityAuthForCategory Adds the category security authentication. Set GroupGuid to null when setting to a special role string categoryGuid, int order, string action, bool allow, string groupGuid, int specialRole, string authGuid
DeleteSecurityAuthForCategory Deletes the security authentication for category. string categoryGuid

SecurityAuthForEntityType

Method Description Signature
AddSecurityAuthForEntityType Adds the security auth record for the given entity type and group. string entityTypeName, int order, string action, bool allow, string groupGuid, int specialRole, string authGuid

SecurityAuthForGroupType

Method Description Signature
AddSecurityAuthForGroupType Adds the page security authentication. Set GroupGuid to null when setting to a special role string groupTypeGuid, int order, string action, bool allow, string groupGuid, Rock.Model.SpecialRole specialRole, string authGuid
DeleteSecurityAuthForGroupType Deletes the security authentication for groupType. string groupTypeGuid

SecurityAuthForPage

Method Description Signature
AddSecurityAuthForPage Adds the page security authentication. Set GroupGuid to null when setting to a special role string pageGuid, int order, string action, bool allow, string groupGuid, int specialRole, string authGuid
DeleteSecurityAuthForPage Deletes the security authentication for page. string pageGuid

SecurityRoleGroup

Method Description Signature
AddSecurityRoleGroup Adds the security role group. string name, string description, string guid
DeleteSecurityRoleGroup Deletes the security role group. string guid

Site

Method Description Signature
AddSite Adds a new Layout to the given site. string name, string description, string theme, string guid
DeleteSite Deletes the Layout. string guid

SystemEmail

Method Description Signature
DeleteSystemEmail Deletes the SystemEmail. string guid

WorkflowActionEntityAttribute

Method Description Signature
UpdateWorkflowActionEntityAttribute Updates the workflow action entity attribute. string actionEntityTypeGuid, string fieldTypeGuid, string name, string key, string description, int order, string defaultValue, string guid

WorkflowActivityTypeAttribute

Method Description Signature
UpdateWorkflowActivityTypeAttribute Updates the workflow activity type attribute. string workflowActivityTypeGuid, string fieldTypeGuid, string name, string key, string description, int order, string defaultValue, string guid

WorkflowTypeAttribute

Method Description Signature
UpdateWorkflowTypeAttribute Updates the workflow type attribute. string workflowTypeGuid, string fieldTypeGuid, string name, string key, string description, int order, string defaultValue, string guid