Skip to main content
All docs
V23.2

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

  1. 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; }
    
    }
    
  2. 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.

    Tip

    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.

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 the 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 the 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 an 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.

  1. 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 (CTP). To find out which precise version you have, check the Microsoft.EntityFrameworkCore package in the dependencies of the YourProjectName.Module project.

  2. 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 code below:

    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.

  3. In Visual Studio, open the Package Manager Console and use the following command to add a migration:

    add-migration MyInitialMigrationName -StartupProject "MySolution.Module" -Project "MySolution.Module"
    
  4. 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

  1. 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 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.

  2. Add another migration and update the database.

  3. 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
    XAF ASP.NET Core Blazor App List View
    Windows Forms
    XAF Windows Forms App List View
  4. 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
    ASP.NET Core Blazor List View
    Windows Forms
    XAF Windows Forms List View

Next Lesson

Extend the Data Model

See Also