We upgraded both CMS and Commerce a few weeks ago. We did not encounter any major issues while upgrading Commerce however I would like to point two issues worth sharing.
We had a plan to update EPiServer to version 7.19.2. It wasn’t the latest available nuget version, but we couldn’t upgrade directly to version 8. I didn’t want to risk and that’s why I chose Commerce package with similar release date. The closest one was 8.6.1.

Nuget dependencies

There is quite a lot of packages to update. Most of them have dependencies between themselves.
nuget packages

My first try was to update all EPiServer packages directly from Nuget Package Manager Console starting from the main package:

I got an exception related with nuget packeges dependencies. Then I tried to update Commerce packages first, starting from Commerce package root. I got the same nuget exception. In both scenarios the problem was related to EPiServer.Common.Framework nuget which is now obsolete in EPiServer CMS and EPiServer Commerce.

While updating the EPiServer CMS, the NPM tried to remove EPiServer.Common.Framework while it was still in use by the old Commerce version and vice versa.When I tried to update Commerce packages first, the NPM tried to delete EPiServer.Common.Framework while it was still used by old version of EPiServer packages.

I ended up with uninstalling all Commerce libraries, then updating EPiServer nugets and then installing specific version of Commerce nugets once again. It was a time consuming process because our solution is divided into several projects. Each of those projects has nuget dependencies on some of EPiServer and Commerce packages, so I had to do this very carefully.

Finally, after solving the conflicts with references I maneged to get rid of all the compilation errors.

Types registration

Unfortunately that was not the end…

I already had my code updated so the next thing to do was to update the database. I did it using the Update‑EPiDatabase NPM Console command. All scripts were executed correctly, so I tried to run the application. Start page (and whole front-end) worked correctly, but when I logged into Edit mode I got this exception:

commerce upgrade exception

Could not create instance of content type “SysCampaignFolder” since it has an invalid .NET class associated: EPiServer.Core.CampaignFolder,EPiServer

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: EPiServer.Core.EPiServerException: Could not create instance of content type "SysCampaignFolder" since it has an invalid .NET class associated: EPiServer.Core.CampaignFolder,EPiServer
Source Error:
The source code that generated this unhandled exception can only be shown when compiled in debug mode. To enable this, please follow one of the below steps, then request the URL:

1. Add a "Debug=true" directive at the top of the file that generated the error. Example:
  <%@ Page Language="C#" Debug="true" %>
or:

2) Add the following section to the configuration file of your application:

<configuration>
   <system.web>
       <compilation debug="true"/>
   </system.web>
</configuration>

Note that this second technique will cause all files within a given application to be compiled in debug mode. The first technique will cause only that particular file to be compiled in debug mode.
Important: Running applications in debug mode does incur a memory/performance overhead. You should make sure that an application has debugging disabled before deploying into production scenario.
Stack Trace:

[EPiServerException: Could not create instance of content type "SysCampaignFolder" since it has an invalid .NET class associated: EPiServer.Core.CampaignFolder,EPiServer]
   EPiServer.Construction.ContentFactory.CreateInstance(ContentType contentType) +564
   EPiServer.Construction.ContentFactory.CreateContent(ContentType contentType, BuildingContext buildingContext) +46
   EPiServer.Commerce.Catalog.Provider.Construction.CatalogContentFactory.CreateContent(ContentType contentType, BuildingContext buildingContext) +144
   EPiServer.DataAccess.ContentLoadDB.LoadContentInternal(ContentReference contentLink, Int32 languageBranchId, DbDataReader reader) +334
   EPiServer.DataAccess.<>c__DisplayClass1.b__0() +285
   EPiServer.Data.Providers.<>c__DisplayClass11.b__0() +60
   EPiServer.Data.Providers.SqlTransientErrorsRetryPolicy.Execute(Func1 method) +150
   EPiServer.Core.<>c__DisplayClass26.b__24() +141
   EPiServer.Core.OptimisticCache1.Read(String cacheKey, ReadAndCacheObject1 readAndCacheObject) +1175
   EPiServer.Core.ContentProvider.LoadContentFromCacheOrRepository(ContentReference contentreference, ILanguageSelector selector) +945
   EPiServer.Core.DefaultContentLoader.TryGet(ContentReference contentLink, LoaderSettings loaderSettings, T& content) +669
   EPiServer.Core.DefaultContentLoader.Get(ContentReference contentLink, LoaderSettings loaderSettings) +90
   EPiServer.Core.DefaultContentLoader.Get(Guid contentGuid, LoaderSettings loaderSettings) +151
   EPiServer.Core.DefaultContentLoader.Get(Guid contentGuid, ILanguageSelector selector) +126
   EPiServer.Core.DefaultContentLoader.Get(Guid contentGuid) +143
   EPiServer.Core.CampaignFolder.GetCampaignRoot() +160
   System.Lazy1.CreateValue() +455
   System.Lazy1.get_Value() +14390282
   GetRoots(Object ) +94
   Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target) +384

[JsonSerializationException: Error getting value from 'Roots' on 'EPiServer.Commerce.Shell.UIDescriptors.MarketingRepositoryDescriptor'.]
   Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target) +564
   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue) +217
   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) +1335
   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) +1436
   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) +1335
   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) +911
   Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) +178
   Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) +936
   EPiServer.Shell.Web.Mvc.Html.ScriptExtensions.SerializeObject(HtmlHelper html, Object value, String contentType) +255
   ASP.secureui_shell_views_shared_bootstrapper_aspx.__Render__control5(HtmlTextWriter __w, Control parameterContainer) +513
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +131
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +150
   ASP.secureui_shell_views_shared_sleek_master.__Render__control1(HtmlTextWriter __w, Control parameterContainer) +625
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +131
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +150
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +249
   System.Web.UI.Page.Render(HtmlTextWriter writer) +40
   System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer) +65
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +150
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5363

Table tblContentType stores all content types. It’s used by EPiServer to initialize ContentTypeRepository. SysCampaignFolder content type had a backend type set as EPiServer.Core.CampaignFolder, EPiServer in database while there was no such type in EPiSErver assembly. The type is defined in EPiServer.Business.Commerce library.

I searched for similar problems on forum, but with no luck, so the the only solution was to prepare a custom SQL script to manually update the backed type.

After executing the script everything started to work.

A few weeks later I realized that there was no need to prepare a custom SQL. I could just add one more step to our update process. After updating the code I should run the application before running schema update scripts. In that scenario the Episerver automatically registers all new content types and the SysCampaignFolder type will have full qualified assembly assigned correctly. Then running schema update will not create new type in DB so there will be no problem.

Upgrading EPiServer Commerce is not risky or time consuming when you do this frequently. The problems with nugets and type registration were probably caused by long time from last update of our solution.