Hello, I would like to have versioning for assembly with entities, but DataObjects seems to have restriction that does not allow me to do that. To be concrete it is in CanUpgradeFrom method of UpgradeHandler class.

Could you please give me some hints why you perform this check? Maybe I'm just doing something wrong.

asked Apr 09 '19 at 07:11

Oleksandr's gravatar image

Oleksandr
9225

edited Apr 09 '19 at 07:13


One Answer:

Hello Oleksandr,

We do that for a reason. Generally if version of assembly changes then there are some changes in it. DataObjects.Net cannot check what exactly has changed and what effect the changes may make on database so if versions differ you will get an error. I think you would prefer to get an exception instead of data damage which can be in DomainUpgradeMode.Perform. It is one more check which prevents you from that.

I will speak about the case when assembly contains only entities. so any change of than will affect database somehow.

You have such scenarios of upgrade:

1) 0.0.0.0(basically this means you have empty database) -> 1.0.0.0 . In that case you don't need to create any custom upgrade handlers.

2) 1.0.0.0 -> 1.0.0.0 - version is not changed so DataObjects.net considers that there is no changes in model and allows to continue building. No custom upgrade handler needed.

3) 1.0.0.0 -> 1.1.0.0. Something has changed in the assembly so as long as you need to save data in database you will need a custom upgrade handler. Lets say you renamed a field in one of entities. Custom upgrade handler might be like:

    public class Upgrader : Xtensive.Orm.Upgrade.UpgradeHandler
    {
      public override bool CanUpgradeFrom(string oldVersion)
      {
        if (oldVersion==null)
          return true; // database is empty so whatever.

        var oldVersionInstance = Version.Parse(oldVersion);

        //this handler can upgrade the assembly only form version 1.0.x.x to current
        if (oldVersionInstance.Major==1 and oldVersion.Minor==0)
          return true;
        return false;
      }

      protected override void AddUpgradeHints(ISet<UpgradeHint> hints)
      {
        base.AddUpgradeHints(hints);
        // this is the only difference between v1.0.x.x and the current assembly.
        hints.Add(new RenameFieldHint(typeof (Person), "MidName", "Patronymic"));
      }
    }

You just can override CanUpgradeFrom() and return true or false by any algorithm you find reasonable. DataObjects.net gave you information and it is up to you how to use it.

answered Apr 09 '19 at 10:15

Alexey%20Kulakov's gravatar image

Alexey Kulakov
77225

edited Apr 09 '19 at 10:16

Thank you for the answer! I appreciate it.

You mentioned that DataObjects.Net cannot check what exactly has changed, but I guess it is developer responsibility. Code changes without assembly version change are allowed anyway. Would you recomend to use DataObjects.Net built in functionality to perform database migrations on Production environment, or it is better to find different solution?

(Apr 12 '19 at 05:42) Oleksandr Oleksandr's gravatar image

Basically DataObjects.Net allows you to perform any upgrade you want. At least you can use pure SQL-queries during upgrade for something really specific. For the most part you will be able to perform upgrade without SQL queries. It depends on how heavily model is changed...

(Apr 12 '19 at 06:11) Alexey Kulakov Alexey%20Kulakov's gravatar image

New entities or fields are safe operations. DataObjects.Net performs such upgrade without you telling that something has added. Removes, renames and changes of field type require your assistance. You have to add hints to resolve such changes of model. In UpgradeHandlerAddUpgradeHints(ISet<upgradehint> hints) you can add different hints such as RenameTypeHint, RenameFieldHint, RemoveFieldHint, RemoveTypeHint, ChangeTypeHint. Those hints give comparer of old and new model a hint of how to treat this or that change.

(Apr 12 '19 at 06:16) Alexey Kulakov Alexey%20Kulakov's gravatar image

We also provide UpgradeHandler.OnUpgrade() method. Within this method you have access to session and transaction (do not dispose or commit them).Open session gives you ability to query data, create new entities, change them or remove. So you can manipulate data as you want. So called recycled entities or recycled fields will be accessible within UpgradeHandler.OnUpgrade() method.

(Apr 12 '19 at 06:25) Alexey Kulakov Alexey%20Kulakov's gravatar image

Overall, you have a lot of information in inheritor of UpgradeHandler class to perform almost any upgrade, including the information in UpgradeHandler.UpgradeContext property and specific information passing to specific methods of UpgradeHandler.

(Apr 12 '19 at 06:34) Alexey Kulakov Alexey%20Kulakov's gravatar image

But do backups before upgrading production database, even just in case.

(Apr 12 '19 at 06:35) Alexey Kulakov Alexey%20Kulakov's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

powered by OSQA