Bug Report T451078
Visible to All Users

XPO - Old business class assemblies may be loaded from the application folder or GAC and cause side effects in .NET Framework apps (due to outdated XPObjectType records)

created 8 years ago (modified 4 years ago)

Hi Guys,

we are having some problem after upgrading to 16.1.7. As you know XPObjectType table contains old assembly names, and so it seems there is a Problem when an Client has both DevExpress.ExpressApp.v16.1.dll and DevExpress.ExpressApp.v14.1.dll in its directory. Our updater currently deletes all old devex assemblies, but when this fails (because for example of restricted rights) - the client cannot open any detailviews anymore. we can solve this by either delete all devex 14.1 dll's - or by upgrading the xpobjecttype table manually. can you please look at this situation, either change the method how you create the detailpropertyeditor? - or provide an out of the box updater for the xpobjecttype table? (see other ticket).

Type:       ObjectCreatingException
                Message:    Unable to create an instance of the "DevExpress.ExpressApp.Editors.DetailPropertyEditor" type.
Reason: "Der Konstruktor für den Typ "DevExpress.ExpressApp.Editors.DetailPropertyEditor" wurde nicht gefunden."
.ctor(System.RuntimeType, ModelPropertyEditor) is absent.,
stack trace: "   bei System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
   bei System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   bei System.Activator.CreateInstance(Type type, Object[] args)
   bei DevExpress.ExpressApp.Utils.Reflection.TypeData.CreateInstance(Object[] args)"
end stack trace
              Data:       0 entries
                Stack trace:
bei DevExpress.ExpressApp.Utils.Reflection.TypeData.CreateInstance(Object[] args)
   bei DevExpress.ExpressApp.Editors.EditorsFactory.CreateViewItem(Type viewItemType, String viewItemId, Boolean checkConstructor, Type objectType, IModelNode modelViewItem)

   bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
                ----------------
                InnerException:

Type:       MissingMethodException
                                               Message:    Der Konstruktor für den Typ "DevExpress.ExpressApp.Editors.DetailPropertyEditor" wurde nicht gefunden.
                                               Data:       0 entries
                                               Stack trace:

bei System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
   bei System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   bei System.Activator.CreateInstance(Type type, Object[] args)
   bei DevExpress.ExpressApp.Utils.Reflection.TypeData.CreateInstance(Object[] args)
                                               InnerException is null

Show previous comments (15)
Dennis Garavsky (DevExpress) 8 years ago

    Thanks for your update, Noxe - we will take it into account when prioritizing our work

    M M
    Martin Praxmarer - DevExpress MVP 8 years ago

      thx Dennis

      M M
      Martin Praxmarer - DevExpress MVP 8 years ago

        fyi - having the same Problem now localy when upgrading to 17.1 and both 16.1 and 17.1 are installed on the machine

        Answers approved by DevExpress Support

        created 7 years ago (modified 4 years ago)

        Problem scenarios

        In .NET Framework apps, the problem may occur when old business class libraries exist in the application folder or in GAC. By default, XPO tries to load them by the XPObjectType info along with the new versions. This may lead to a conflict at runtime (for instance, ObjectCreatingException) or startup performance degradation. In the latter case, assembly type resolution may come at a cost (see the point 3.5 under How to measure and improve the application's performance).

        NOTE: This behavior does NOT occur in .NET Core/.NET 5+ apps - the assembly discovery logic differs form the logic of .NET Framework apps: Default Probing. According to the documentation, a .NET Core app uses the *.deps.json file to determine where to look for files. A .NET Core app scans the entire app directory only if the *.deps.json file isn't present. To keep the previous behavior in XAF apps, you can use the internal and undocumented ReflectionHelper.AddResolvePath method: DevExpress.Persistent.Base.ReflectionHelper.AddResolvePath(System.AppDomain.CurrentDomain.BaseDirectory);. For more information, see T996162.

        Why are we hesitating to remove old XPObjectType entries by default?

        1.  Removing old XPObjectType records affects other apps accessing this database and is serious. Outdated service table records may relate to business class records too (inheritance mapping is in use very often). So, deleting them will lead to foreign key constraint violation. Creating a sophisticated generic solution for this is not easy task.
        2.   XPObjectType table updates are safe only with the full database and application knowledge. Users possessing this knowledge can use the following prebuilt options:

        In XAF apps

        Call the ModuleUpdater.UpdateXPObjectType method (SQL Server-specific) as shown in the How to: Handle Renamings and Deletions of Business Classes and their Properties article.

        C#
        public class Updater : ModuleUpdater { // ... public override void UpdateDatabaseBeforeUpdateSchema() { base.UpdateDatabaseBeforeUpdateSchema(); if (CurrentDBVersion < new Version("1.1.0.0") && CurrentDBVersion > new Version("0.0.0.0")) { RenameTable("Department", "Division"); UpdateXPObjectType( "MySolution.Module.Department", "MySolution.Module.Division", "MySolution.Module"); } } // ...

        In non-XAF apps

        We demonstrated a database-agnostic updater in the XObjectTypeUpdateNonXAF.zip sample using the service XPObjectType persistent objects.

        C#
        using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using DevExpress.Xpo; using DevExpress.Xpo.DB; namespace ConsoleApplication7 { class Program { static void Main(string[] args) { var cs = MSSqlConnectionProvider.GetConnectionString("localhost", "XPOProjects"); using(var dataLayer = XpoDefault.GetDataLayer(cs, AutoCreateOption.SchemaAlreadyExists)) { using(var uow = new UnitOfWork(dataLayer)) { // You can use ObjectSpace instead of uow in XAF's ModuleUpdater. var result = uow.Query<XPObjectType>().ToList(); // You can use ObjectSpace.GetObjects here in XAF's ModuleUpdater. foreach(var ot in result) { var string oldVersion = "v15.1"; var string newVersion = "v19.1"; if(ot.AssemblyName.Contains(oldVersion)) { ot.AssemblyName = ot.AssemblyName.Replace(oldVersion, newVersion); } uow.Save(ot); } uow.CommitChanges(); // You can use ObjectSpace.CommitChanges here in XAF's ModuleUpdater. } } } } }

        3.  We help XAF developers detect this fact by writing log messages. Check out your eXpressAppFramework.log file for the "Resolve the 'DevExpress.ExpressApp.Workflow.v11.1' assembly"  and similar messages referring to outdated DevExpress assemblies. Of course, a developer or DBA can preview the XPObjectType table using database engine tools.
        4.  Old application assemblies living within the new application folder is unexpected in itself. At least, I would instinctively always prefer a fresh Windows install over an update. Even though we are aware of some specific scenarios (e.g., with plugins or locked assemblies), it is still easy to install the new application version into the new folder. This natural action will avoid these risky circumstances completely.
        5.  Finally, we heard less or almost nothing about this behavior lately. Most likely, this is because an XAF app stores user settings in the database and not in a file system by default and thus the point #4 is simpler.

        Your feedback counts!

        Regardless of the reasoning above, we want to collect more feedback in this regard. Please answer two simple questions here in comments or use the https://www.devexpress.com/ask service:

        1. Did you ever notice negative effects from the outdated type and assembly references in the XPObjectType table?
          2. If so, describe your problems and use-case scenarios in greater detail. Also, comment on their frequency (e.g., once, every year, etc.) as well as on your current solution implementation and maintenance costs, if any.
           
          Thank you very much for your help!
          Comments (1)

            For a maintenance free AssemblyName renaming for the DevExpress libraries. See solution in this ticket: Updating the XPObjectType.AssemblyName using the XPClassInfo.AssemblyName? | DevExpress Support. This will work when DevExpress assembly name changes, but the object namespace remains the same like with Core - Base XPO and EF6 NuGet packages and assemblies have been renamed or removed | DevExpress Support.

            Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

            Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.