Implement a Data Model: Basics
- 7 minutes to read
This lesson explains how to implement entity classes for your application and describes the basics of automatic user interface construction based on data.
During this lesson, you will do the following:
- Add a simple entity class.
- Display the entity class in the application’s navigation control.
Entity classes do not depend on the application UI. Implement them in a platform-independent module project. This way, other XAF or non-XAF applications can share entities.
Inherit your entity classes from the base persistent class DevExpress.Persistent.BaseImpl.EF.BaseObject
. The BaseObject
class implements the IXafEntityObject and IObjectSpaceLink interfaces. This means that CRUD operations for the declared objects are available automatically and you don’t need to implement them in your code.
For additional information on these concepts, refer to the following topic: Views.
Step-by-Step Instructions
Expand the MySolution.Module project and right-click the Business Objects folder. Choose Add | Class…. Specify Employee.cs as the new class name and click Add. Replace the auto-generated code with the following class declaration:
using DevExpress.Persistent.BaseImpl.EF; namespace MySolution.Module.BusinessObjects; public class Employee : BaseObject { public virtual String FirstName { get; set; } public virtual String LastName { get; set; } public virtual String MiddleName { get; set; } }
Go to the MySolution.Module\BusinessObjects\MySolutionDbContext file and add the following property to the
MySolutionEFCoreDbContext
entity container class:using MySolution.Module.BusinessObjects; namespace MySolution.Module.BusinessObjects { public class MySolutionEFCoreDbContext : DbContext { //... public DbSet<Employee> Employees { get; set; } } }
This property is a collection of
Employee
class objects. XAF creates a table with the same name in the database and then maps this collection to the table.Note
- If you inherit an entity class from another entity class, you can register both entities in the
DbContext
class. This way, your application can work with collections of ancestor class objects. XAF’s EF Core implementation does not support the following data model configurations: entities with composite/compound keys (multiple properties as an entity key), keyless entity types, and owned entity types. In such scenarios, inherit your EF Core entity from XAF’s
BaseObject
class or define your own class with a single Guid, numeric (Int32, Int64 ), or String primary key. You can also use non-persistent objects to integrate XAF UI with legacy systems.
- If you inherit an entity class from another entity class, you can register both entities in the
Propagate Data Model Structure Changes to the Database
Your application now contains data objects. This means that the application requires a database. You have the following options to choose from:
Use a DBMS to maintain the database.
This option requires you to set up database migrations.
Use an in-memory database.
This option works best during the development/debugging stage. You only need to update data connection code.
If you cannot work with an in-memory database, you can drop the database after you change the business model. Note that this action clears all previously added data records. If you need to keep data between application runs, update the database whenever you make changes to the data model (create a new class, add a new attribute to an existing class, rename a class or an attribute, and so on).
Use a DBMS: Setup Migrations
Since this tutorial uses Entity Framework Core, changes to the application’s data model may cause database-related exceptions when you run the application. The exception occurs if the database structure does not correspond to the structure of the business model classes.
In this tutorial, we use migrations to update the database schema because this feature is native to EF Core and is quick to implement. Before you run the application for the first time, or anytime after you change the Data Model, you need to create a migration and update the database. To do this, follow the steps below.
Important
Delete the existing database (if there is one) before you proceed, because Entity Framework Core does not take the existing database schema into consideration when it generates the first migration.
Add the Microsoft.EntityFrameworkCore.Tools NuGet package to the MySolution.Module project. Build the solution.
Note
The package’s version must correspond to the version of EF Core supported in XAF.
Currently, we support Entity Framework Core 8.x.x. To find out which precise version you have, check the Microsoft.EntityFrameworkCore package in the dependencies of the YourProjectName.Module project.
In the MySolution.Module project, go to the BusinessObjects folder and open the MySolutionDbContext.cs file. Replace the declaration of the
MySolutionDesignTimeDbContextFactory
class with the following code snippet:namespace MySolution.Module.BusinessObjects; //... public class MySolutionDesignTimeDbContextFactory : IDesignTimeDbContextFactory<MySolutionEFCoreDbContext> { public MySolutionEFCoreDbContext CreateDbContext(string[] args) { // Throw new InvalidOperationException ("Make sure that the database connection string and connection provider are correct. After that, uncomment the code below and remove this exception.") var optionsBuilder = new DbContextOptionsBuilder<MySolutionEFCoreDbContext>(); optionsBuilder.UseSqlServer("Integrated Security=SSPI;Pooling=false;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=MySolution"); //Automatically implements the INotifyPropertyChanged interface in the business objects optionsBuilder.UseChangeTrackingProxies(); optionsBuilder.UseObjectSpaceLinkProxies(); return new MySolutionEFCoreDbContext(optionsBuilder.Options); } }
In the above code sample, the
optionsBuilder.UseChangeTrackingProxies
method enables the change-tracking proxies extension so that the application’s UI correctly reflects changes in data model. Refer to the Change Tracking in EF Core DbContext and Performance Considerations article for more information on change tracking in XAF applications with Entity Framework Core data models.In Visual Studio, open the Package Manager Console and use the following command to add migration:
add-migration MyInitialMigrationName -StartupProject "MySolution.Module" -Project "MySolution.Module"
Update the database with the following command:
update-database -StartupProject "MySolution.Module" -Project "MySolution.Module"
You must update the database whenever you change the data model of your application. For example, when you add, rename, or delete a class or property. To do this, repeat steps 3 and 4 of this tutorial. Make sure to use a unique migration name for each new migration.
Use an In-memory Database
Open the MySolution.Blazor.Server\Startup.cs file, comment the UseSqlServer
option, and uncomment the UseInMemoryDatabase
option as displayed in the code snippet below. Do the same in the MySolution.Win\Startup.cs file.
//..
namespace MySolution.Blazor.Server;
public class Startup {
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// ...
public void ConfigureServices(IServiceCollection services) {
services.AddSingleton(typeof(Microsoft.AspNetCore.SignalR.HubConnectionHandler<>), typeof(ProxyHubConnectionHandler<>));
//...
services.AddXaf(Configuration, builder => {
//...
builder.ObjectSpaceProviders
.AddEFCore().WithDbContext<MySolution.Module.BusinessObjects.MySolutionEFCoreDbContext>((serviceProvider, options) => {
// ...
options.UseInMemoryDatabase("InMemory");
string connectionString = null;
if(Configuration.GetConnectionString("ConnectionString") != null) {
connectionString = Configuration.GetConnectionString("ConnectionString");
}
//...
ArgumentNullException.ThrowIfNull(connectionString);
//options.UseSqlServer(connectionString);
options.UseChangeTrackingProxies();
options.UseObjectSpaceLinkProxies();
options.UseLazyLoadingProxies();
})
// ...
});
}
}
Application Run
Run the application. You can see that the UI did not change. To make the
Employee
item visible in the application’s navigation control, add the DefaultClassOptionsAttribute attribute to the corresponding class://... namespace MySolution.Module.BusinessObjects; [DefaultClassOptions] public class Employee : BaseObject { //... } //...
With this attribute, you can also use
Employee
objects as data sources to generate reports. For additional information, refer to the following lesson of this tutorial: Create and Preview a Report.To apply each option separately, use the NavigationItemAttribute and VisibleInReportsAttribute attributes.
Run the application. XAF generates a user interface that is based on the specified data structures. The List View displays the collection of objects of the
Employee
class. Since there are no objects of this type, the Employee List View is empty for now:- ASP.NET Core Blazor
- Windows Forms
Click the New button to invoke the Detail View for a new object of the
Employee
type. XAF renders the properties of the entity class as data fields. The Detail View contains editors for each data field.- ASP.NET Core Blazor
- Windows Forms