Custom bundle migrations fail at first install because they run before OroCommerce's installers - orocommerce

I created a custom bundle in which I have a few migrations, among them is one that adds a field to the Product entity, making the oro_product table a dependency for this migration to run.
The problem is that when I run the oro:install command, it runs the migrations, but fails at the beginning because it runs my custom bundle's migrations first, and that won't work because the oro_product table doesn't exist at this point in time.
Is there a way to control in which order the migrations are executed, or is there something else to do to avoid this issue?
Thanks!

To load the schema migration later, you can set the higher bundle priority in the <BundleDirectory>/Resources/config/oro/bundles.yml file. E.g.:
bundles:
- { name: Acme\Bundle\DemoBundle\AcmeDemoBundle, priority: 1000 }

Related

How to run migrations of another app from main app

I am following umbrella apps structure in my project. and I am writing access layer app which doesn't have separate repo but requires to have certain tables and relations migrated for it to work. I dont wanna create separate repo for it and make it complex to maintain configs etc.
I have tried following two approaches
defmodule Data.Repo.Migrations.CreateActions do
use Ecto.Migration
def change do
# First approach
opts = []
file_path = ExAcl.SeedHelper.priv_path_for("20181129092126_create_actions.exs", app: :acl)
Ecto.Migrator.run(Data.Repo, file_path, :up, opts)
{:ok, _} = Application.ensure_all_started(:acl)
# Second approach
Ecto.Migrator.up(HaiData.Repo, 20181129092126, ExAcl.Repo.Migrations.CreateActions)
end
end
But It doesn't run migrations in another app.
Maybe I am not going in right direction. I am not sure what is the best way to run migration in another app
Goal: run migrations in acl app via main data app.
If you try to run a migration via Ecto.Migrator.run from inside another migration, then you will most likely run into database locks, because Ecto doesn't allow you to run migrations concurrently.
If you want to use this approach, then you can do this:
def change do
file_path = ExAcl.SeedHelper.priv_path_for("20181129092126_create_actions.exs", app: :acl)
Code.require_file(file_path)
ModuleInTheMigrationFile.change()
end
But I am not sure how maintainable this would be in the long term. If there are other migrations, then you would have to explicitly require and invoke each migration one by one. And then what happens for new migrations in the future? Therefore I propose one of:
If you want to do execute only one migration and only once, simply copy the migration file to your migrations folder
If the two migrations folders are evolving side by side and you would like to automatically run migrations from both directories, you can invoke ecto.migrate twice:
mix ecto.migrate --migrations-path priv/repo/migrations
mix ecto.migrate --migrations-path other/app/priv/repo/migrations
If the two migrations folders are evolving side by side and you would like to manually run migrations from both directories, you can copy the migrations from one directory to the other and keep only one directory as source of truth

Proper way to work with migrations during development

How to properly work with migrations during development when the model is not in its final form or there are still some inconsistencies in relations?
Should migrations be treated more as commits in version control system like git and represent even the smallest change, or what?
Should I add new migration for each small change in my model, or should I just re-create the database and initial migration until I'm satisfied with how my model looks? I can still remove all those migrations in the end and create initial one to clean those small migrations up.
How to properly name migrations? Most often I can't come up with a good name and I give them some meaningless names like X1, X2, X3
Similar questions:
How to deal with database changes during development with EF Core?
1: I personally would keep it as a history. Of course you could always delete all migrations and create one that contains everything but imagine that migration after you have added 100++ tables (entity-types) and you cannot make sure your production database for instance is being updated, when you only have one migration with same name that you just always recreate.
2: Yes, you should indeed make small migrations. You can undo a migration by updating your database to a specific migration and then removing all the others before step by step. This at least works with the package-manager-console tool (maybe also with dotnet tool).
For instance you have already added a migration with models that have changed you go back to the old migration by using this command:
Update-Database -Migration MyMigrationBeforeBadModelMigration
Be aware that this might drop tables if some were added in the migration that you want to undo.
Then remove bad migrations step by step
Remove-Migration // will always remove the latest migration so repeat that if you have many to remove
Then just create the new and proper migration and update your db.
3: Yes, give them proper names. For instance CustomerEntityAdded or CustomerUniqueNameIndexAdded.

How to run Sequelize down migration for single file

I'm working on a migration using Sequelize. If the migration up method throws an error, the migration is not logged in the database as having completed. So, if I run db:migrate:undo, it instead runs down on the previous (and working) migration. As a result, I have a half executed migration where the schema for it remains in the database because the corresponding down method is never run by Sequelize. So, I need to either somehow force a single down method to run (which I'm not seeing an option for). Or, I need to manually clean up my database every time I run a failing migration, which can be a real pain for complicated migrations where I'm constantly going through trial and error. Is there an easier way to doing this?
sequelize db:migrate:undo --name 20200409091823-example_table.js
Use this command to undo any particular migration
manually insert the migration into your migrations table so that sequelize will think it has completed.
To verify check the status of your migrations before and after you edit the table.
db:migrate:status
Everything listed as "up" is something that can go "down" and vice versa.
There is no way to do it as of now... There is an open issue for this in Sequelize cli repo
I tried something and it worked for me:
rename your migration file and make sure it comes first alphabetically (make it the first one in migration files)
comment code in the second migration file
run sequelize db:migrate
This will run only the first migration file.
Don't forget to uncomment the migration file you commented before

Do I use Snapshot file, migration file or data annotations in my EF Core to update database?

I'm trying to understand the different types of migration paths we can choose when developing an ASP.NET Core 1.0 application with EF Core. When I created my first Core application I noticed it generated a ApplicationDbContextModelSnapshot class that uses a ModelBuilder to build the model.
Then I read that if I need to add a table to the database, I need to create the new model and run the command line to generate the migration file and update the database. Ok, I get it up to this point.
But when I do that, I notice that the ApplicationDbContextModelSnapshot class gets updated too.
1) Does that mean I cannot modify this ApplicationDbContextModelSnapshot class since it looks like it gets regenerated each time?
2) Should I use Data Annotations to build my model or should I use Fluent API which tells me to build my model in the ApplicationDbContext class? Huh? another file that builds the model?
I'm seeing three different ways of working with the database here, the snapshot class, data annotations, and fluent API. I'm confused because today, I made a mistake in my last migration file so I deleted the file, dropped the database and reran the database update.
But by doing that I got errors similar to:
The index 'IX_Transaction_GiftCardId' is dependent on column 'GiftCardId'.
ALTER TABLE ALTER COLUMN GiftCardId failed because one or more objects access this column.
So naturally I was wondering if I had to modify the ApplicationDbContextModelSnapshot class.
What is the path I should be taking when it comes to migrations or database updates because these three paths are confusing me.
I have run into this issue before when I create migrations, make model changes, create new migrations, and try to update the database. The root cause is when keys are being changed and relationships are not dropped and are not added back or do not exist.
You have two options
Easy Method
The easiest way is also the most destructive way and only possible in a dev environment.
Delete all migrations, drop the database, create new migrations and run 'update-database'.
Hard/Safest Method
This is the most time consuming method. I recommend do this in a local integration branch first, pushing it to a remote integration, and then production.
Open the migration file, ie 20160914173357_MyNewMigration.cs.
Drop all indexes in order
Drop/Add/Edit table schemas
Add all indexes back.
For either method, just be sure to test and test again.
Do not modify ApplicationDbContextModelSnapshot. It is a design-time artifact, and should only be modified in the case of a merge conflict.
To update the model, always use data annotations or the fluent API.
For more information on the EF Migrations workflow, see Code First Migrations. It's for EF6, but most of the information is still relevant.

Can Liquibase detect if it has already run?

I have a small set of scripts that manage the build/test/deployment of an app. Recently I decided I wanted to switch to Liquibase for db schema management. This script will be working both on the developer machines where it regularly blow away and rebuild their database and also on deployed environment where we will only be adding new changesets.
When this program first runs on a deployed environment I need to detect if Liquibase has run or not and then run changelogSync to sync with the existing tables.
Other than manually checking if the database changelog table exists is there a way for the Liquibase API to let me know that it has already run at least once?
I'm using the Java core library in Groovy
The easiest way is probably ((StandardChangeLogHistoryService) ChangeLogHistoryServiceFactory.getInstance().getChangeLogService(database)).hasDatabaseChangeLogTable()
The ChangeLogHistoryService interface returned by liquibase.changelog.ChangeLogHistoryServiceFactory doesn't have a method to check if the table exists, but the StandardChangeLogHistoryService implementation does.