What Happened
In v22.2, we refactored the DevExpress.Persistent.BaseImpl.EFCore library to make the XAF platform easier to use and to align it with the Entity Framework Core 6 best practices and breaking changes.
All XAF customers who created XAF apps with EF Core 3 or 5 and who want to upgrade to XAF v22.2 and EF Core 6 must change their application code and database structure/data.
Note: You may need to apply additional changes unrelated to built-in classes. Please review the following Breaking Change ticket: Core - XAF's Blazor, Web API Service, and WinForms assemblies target EF Core 6 instead of EF Core 5.
What Changed
-
DevExpress.Persistent.BaseImpl.EFCore now contains only persistent classes required for the operation of XAF-specific modules (for example, PermissionPolicyUser, ReportData). The following persistent types were removed from the assembly:
- DevExpress.Persistent.BaseImpl.EF.Address
- DevExpress.Persistent.BaseImpl.EF.Country
- DevExpress.Persistent.BaseImpl.EF.Note
- DevExpress.Persistent.BaseImpl.EF.Organization
- DevExpress.Persistent.BaseImpl.EF.Party
- DevExpress.Persistent.BaseImpl.EF.Person
- DevExpress.Persistent.BaseImpl.EF.PhoneNumber
- DevExpress.Persistent.BaseImpl.EF.Priority
- DevExpress.Persistent.BaseImpl.EF.Task
- DevExpress.Persistent.BaseImpl.EF.TitleOfCourtesy
-
The following classes changed the key property type from
System.Int32
toSystem.Guid
:- DevExpress.ExpressApp.EFCore.Updating.ModuleInfo
- DevExpress.Persistent.BaseImpl.EF.Analysis
- DevExpress.Persistent.BaseImpl.EF.DashboardData
- DevExpress.Persistent.BaseImpl.EF.Event
- DevExpress.Persistent.BaseImpl.EF.FileAttachment
- DevExpress.Persistent.BaseImpl.EF.FileData
- DevExpress.Persistent.BaseImpl.EF.HCategory
- DevExpress.Persistent.BaseImpl.EF.Kpi.BaseKpiObject
- DevExpress.Persistent.BaseImpl.EF.MediaDataObject
- DevExpress.Persistent.BaseImpl.EF.ModelDifference
- DevExpress.Persistent.BaseImpl.EF.ModelDifferenceAspect
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyActionPermissionObject
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyMemberPermissionsObject
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyNavigationPermissionObject
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyObjectPermissionsObject
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyRoleBase
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyTypePermissionObject
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyUser
- DevExpress.Persistent.BaseImpl.EF.ReportDataV2
- DevExpress.Persistent.BaseImpl.EF.Resource
- DevExpress.Persistent.BaseImpl.EF.RichTextMailMergeData
- DevExpress.Persistent.BaseImpl.EF.State
- DevExpress.Persistent.BaseImpl.EF.StateMachine.StateMachine
- DevExpress.Persistent.BaseImpl.EF.StateMachine.StateMachineAppearance
- DevExpress.Persistent.BaseImpl.EF.StateMachine.StateMachineState
- DevExpress.Persistent.BaseImpl.EF.StateMachine.StateMachineTransition
- DevExpress.Persistent.BaseImpl.EFCore.AuditTrail.AuditDataItemPersistent
- DevExpress.Persistent.BaseImpl.EFCore.EFCoreWeakReference
- DevExpress.Workflow.EF.EFInstanceKey
- DevExpress.Workflow.EF.EFTrackingRecord
- DevExpress.Workflow.EF.EFWorkflowInstance
-
The
INotifyPropertyChanged
interface implementation and theSetPropertyValue
/SetReferencePropertyValue
methods were removed from the following classes:- DevExpress.ExpressApp.EFCore.Updating.ModuleInfo
- DevExpress.Persistent.BaseImpl.EF.Analysis
- DevExpress.Persistent.BaseImpl.EF.DashboardData
- DevExpress.Persistent.BaseImpl.EF.Event
- DevExpress.Persistent.BaseImpl.EF.FileAttachment
- DevExpress.Persistent.BaseImpl.EF.FileData
- DevExpress.Persistent.BaseImpl.EF.HCategory
- DevExpress.Persistent.BaseImpl.EF.Kpi.BaseKpiObject
- DevExpress.Persistent.BaseImpl.EF.MediaDataObject
- DevExpress.Persistent.BaseImpl.EF.ModelDifference
- DevExpress.Persistent.BaseImpl.EF.ModelDifferenceAspect
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyMemberPermissionsObject
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyNavigationPermissionObject
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyObjectPermissionsObject
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyRoleBase
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyTypePermissionObject
- DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyUser
- DevExpress.Persistent.BaseImpl.EF.ReportDataV2
- DevExpress.Persistent.BaseImpl.EF.Resource
- DevExpress.Persistent.BaseImpl.EF.RichTextMailMergeData
- DevExpress.Persistent.BaseImpl.EF.State
- DevExpress.Persistent.BaseImpl.EF.StateMachine.StateMachineAppearance
- DevExpress.Persistent.BaseImpl.EF.StateMachine.StateMachineState
- DevExpress.Persistent.BaseImpl.EF.StateMachine.StateMachineTransition
- DevExpress.Workflow.EF.EFInstanceKey
- DevExpress.Workflow.EF.EFTrackingRecord
- DevExpress.Workflow.EF.EFWBaseObject
- DevExpress.Workflow.EF.EFWorkflowInstance
You do not need to replace these methods with other code.
Reasons for Change
-
The
Employee
,Department
,Task
, and other business entity classes are not required by the XAF platform and were intended for demonstration purposes only. It is not recommended to use these classes and their derived types in real business applications. We recommend that you create your business classes instead and extend or modify their code as needed, without unnecessary complexities caused by inheritance and unused methods. -
in many cases, correct operation of an XAF application requires that an object receives a unique key value before it is stored in the database. Entity Framework Core does not generate a unique value for
Int32
key properties when the new object is created, but does it forGuid
key properties. Use keySystem.Guid
key properties as a recommended practice for all business objects. If you switch toGuid
primary keys, make sure to run regular database maintenance. Lack of maintenance may lead to database index fragmentation and performance degradation over time. -
XAF v22.2 applications use EF Core Change-tracking proxies to add the INotifyPropertyChanged interface to all persistent objects at runtime automatically. An explicit implementation of the
INotifyPropertyChanged
interface is no longer required in most cases. This leads to cleaner code and saves developer time.
Impact on Existing Apps
-
If your application uses classes that are removed from the Business Class Library, a compilation error occurs.
To avoid compilation errors, add all missing business object classes to your application. You can find the source code of the business classes removed from the DevExpress.Persistent.BaseImpl.EFCore assembly in the attached archive: DevExpress.Persistent.BaseImpl.EFCore_Removed_Business_Classes.zip. -
A runtime error occurs when the application starts if the database is not updated according to EF Core 6 changes in v22.2. To convert the type of primary key fields in the database, compile and run the
KeyConverterIntToGuidUI
utility. The source code of this utility is attached to this ticket: KeyConverterIntToGuidUI.zip. Note that this version of the utility supports Microsoft SQL Server databases only. If your application uses another RDBMS, you can modify the converter utility. If object key properties are accessed in your application code directly (for instance, you cast a key toInt32
), a compilation error may occur due to property type changes. In this case, you need to correct your code manually (for instance, cast it toGuid
).
If your application has anApplicationUserLoginInfo
class that was automatically generated by the XAF Solution Wizard, you need to change itsID
andUserForeignKey
properties' type fromint
toGuid
. Rewrite theApplicationUserLoginInfo
class as follows:C#[Table("PermissionPolicyUserLoginInfo")] public class ApplicationUserLoginInfo : ISecurityUserLoginInfo { public ApplicationUserLoginInfo() { } [Browsable(false)] public virtual Guid ID { get; protected set; } [Appearance("PasswordProvider", Enabled = false, Criteria = "!(IsNewObject(this)) and LoginProviderName == '" + SecurityDefaults.PasswordAuthentication + "'", Context = "DetailView")] public virtual string LoginProviderName { get; set; } [Appearance("PasswordProviderUserKey", Enabled = false, Criteria = "!(IsNewObject(this)) and LoginProviderName == '" + SecurityDefaults.PasswordAuthentication + "'", Context = "DetailView")] public virtual string ProviderUserKey { get; set; } [Browsable(false)] public virtual Guid UserForeignKey { get; set; } [Required] [ForeignKey(nameof(UserForeignKey))] public virtual ApplicationUser User { get; set; } object ISecurityUserLoginInfo.User => User; }
Please contact us if you encounter any issues.
-
Since the
INotifyPropertyChanged
interface is no longer implemented in objects, the application UI cannot handle business object property changes. This can lead to incorrect data and control display in the application UI.
To make Entity Framework Core automatically add anINotifyPropertyChanged
interface implementation, use the DbContextOptions.UseChangeTrackingProxies() extension method when you configure yourDbContext
:C#// ... dbContextOptions.UseSqlServer(connectionString); dbContextOptions.UseLazyLoadingProxies(); dbContextOptions.UseChangeTrackingProxies(); // ...
Add
options.UseChangeTrackingProxies()
in the following files:- SolutionName.Win/ApplicationBuilder.cs (the WithDbContext or WithAuditedDbContext methods)
- SolutionName.Blazor.Server/WebApi/Startup.cs (the WithDbContext or WithAuditedDbContext methods)
- SolutionName.Module/SolutionNameDbContext.cs (the SolutionNameContextInitializer and SolutionNameDesignTimeDbContextFactory classes)
You also need to override the
OnModelCreating()
method in yourDbContext
, and add the following code:C#public class ApplicationDbContext : DbContext { // ... protected override void OnModelCreating(ModelBuilder modelBuilder) { // ... modelBuilder.HasChangeTrackingStrategy(ChangeTrackingStrategy.ChangingAndChangedNotificationsWithOriginalValues); } }
For additional details on how to configure the Change-tracking proxies in Entity Framework Core, refer to the following documentation topic: Change Detection and Notifications - Change-tracking proxies.