Marten: ApplyAllConfiguredChangesToDatabase confusion

Created on 24 Jul 2019  路  12Comments  路  Source: JasperFx/marten

Given a brand new database, running the following throws a SchemaValidationException as expected

var store = DocumentStore.For(_ =>
{
    _.Connection("a_connection_string");
    _.AutoCreateSchemaObjects = AutoCreate.None;
});

store.Schema.AssertDatabaseMatchesConfiguration();


SchemaValidationException details
Configuration to Schema Validation Failed! These changes detected:

CREATE OR REPLACE FUNCTION public.mt_immutable_timestamp(value text) RETURNS timestamp without time zone LANGUAGE sql IMMUTABLE AS $function$
select value::timestamp
$function$;

CREATE OR REPLACE FUNCTION public.mt_immutable_timestamptz(value text) RETURNS timestamp with time zone LANGUAGE sql IMMUTABLE AS $function$
select value::timestamptz
$function$;
....etc

After reading the documentation, I assumed I could call:

store.Schema.ApplyAllConfiguredChangesToDatabase();

To programmatically apply all detectable schema changes upfront when an application is first bootstrapped, you can use this mechanism:

However this appears to do nothing.

Running the following code causes the same SchemaValidationException

var store = DocumentStore.For(_ =>
{
    _.Connection("a_connection_string");
    _.AutoCreateSchemaObjects = AutoCreate.None;
});

store.Schema.ApplyAllConfiguredChangesToDatabase();
store.Schema.AssertDatabaseMatchesConfiguration();

I'm trying to get marten to not apply schema changes automatically, but rather only when I call ApplyAllConfiguredChangesToDatabase.

question schema management

All 12 comments

@michael-wolfenden that might be resolved by https://github.com/JasperFx/marten/pull/1321, but I'll double check that.

@michael-wolfenden I initially misread your issue. After investigation I think that current mechanism is working as designed.

ApplyAllConfiguredChangesToDatabase method applies the changes based on your autocreate configuration. So if you setup:

  • All it will do full drop/create etc.
  • CreateOrUpdate will not drop any existing objects
  • Create won't drop and not update any existing objects,
  • None won't do any changes
    So if you setup None then you won't be able to generate any update script. Marten provides also 2 methods:
  • ToDDL that generates string with all potential changes
  • WriteDDL that will do the same as ToDDL but write it to file.

You can use the script generated and just call it through NpgsqlConnection (it can be taken from DocumentSession).

In theory we could:

  • provide some parameter like to ApplyAllConfiguredChangesToDatabase like - force,
  • or add another method for doing manual schema update
  • or add new enum value to AutoCreate like manual
    although I'm not convinced if that'd be the best option as that might be at the end misleading and overused by the users.

@michael-wolfenden @jeremydmiller @mysticmind @jokokko thoughts?

@oskardudycz If I set AutoCreateSchemaObjects to anything other than None then doesn't marten automatically apply the changes (i.e. calling ApplyAllConfiguredChangesToDatabase is redundant at that point).

If that is the case, then the only time I would want to call ApplyAllConfiguredChangesToDatabase is if AutoCreateSchemaObjects is set to None. I'm telling marten, don't automatically apply any changes only apply them when I call ApplyAllConfiguredChangesToDatabase.

I am able to work around it by generating the patch and applying it myself as you suggested, so I'm happy to close out this issue.

I'm just confused as to the purpose of ApplyAllConfiguredChangesToDatabase

As I wrote above ApplyAllConfiguredChangesToDatabase applies the changes based on the AutoCreate option that you've chosen. If you use None then it won't apply any changes.

Currently ou can use ToDDL method to generate the differential script and then run it manually - eg. through NpgsqlConnection.

But aren't your changes applied based on the AutoCreate option anyway without you needing to call ApplyAllConfiguredChangesToDatabase

Yes, they will be applied even if you didn't call ApplyAllConfiguredChangesToDatabase but only on demand (so eg. when you try to add document of exact type). ApplyAllConfiguredChangesToDatabase does that in advance so no further changes will be applied during the application lifetime.

Ahhh.. now I understand. Thanks for clarifying @oskardudycz. I'll close this issue out now.

Cool - I'm happy that I was able to help 馃槂 馃憤

Relooking at the above, I think the requirement to run ApplyAllConfiguredChangesToDatabase() independent of the StoreOptions.AutoCreateSchemaObjects is valid.

If StoreOptions.AutoCreateSchemaObjects is anything other than AutoCreate.None then the DocumentStore will auto-create schema objects accordingly on first run. In this case, running ApplyAllConfiguredChangesToDatabase() manually does not make much sense.

If the user wants to control and decide when to apply scheme changes, the user can set the StoreOptions.AutoCreateSchemaObjects to AutoCreate.None and run ApplyAllConfiguredChangesToDatabase() as they see it fit. This is the use case which @michael-wolfenden was trying to achieve. Earlier we had our default as AutoCreate.All, this use case was working fine but this got broken after we updated the default as AutoCreate.CreateOrUpdate. Also running ApplyAllConfiguredChangesToDatabase() should be independent of StoreOptions.AutoCreateSchemaObjects settings.

@oskardudycz I will send a PR which will allow for the above scenario. Please review and let me know your thoughts.

@mysticmind the only thing that we should be aware is that user might want to apply changes based on the different criteria. I can imagine that user might want to apply changes with create or update manner.
I agree that we should find smart way to untie those two things.

@oskardudycz I have thought through it already, ApplyAllConfiguredChangesToDatabase(AutoCreate withCreateSchemaObjects = AutoCreate.CreateOrUpdate) will be this...

That make sense - by default it could use settings from the AutoCreate.

Was this page helpful?
0 / 5 - 0 ratings