DevExpress XAF Series

XAF Project Setup for EF Core with MySQL

Share This Article

When starting a new project in DevExpress XAF, I follow a series of steps to prepare it for development. I generally develop on a Mac Book Pro, so these steps are geared toward running the process on my Mac Book Pro with an M1 Processor. In this tutorial, I will also be working with DevExpress 23.2.6.

To get started, you’ll need Parallels Desktop with a copy of Windows for ARM and Visual Studio installed. Then, you must install the DevExpress Universal Subscription package to add the necessary tools to your Visual Studio instance. I also like configuring my VM to access my local source directory in MacOS.

I like JetBrains Rider as an IDE on my Mac. Once the project is initialized in Visual Studio, I will do most of my work in MacOS using Rider. I only jump back to my VM to edit the Application Model.

Creating the Project

Let’s start by selecting the XAF C# Template from our list of new project types. You can add a Blazor App, WebAPI, and Winforms App, but if you add the Winforms App, you will need a ton of errors to edit it on the Mac. Additionally, you won’t be able to run the WinForms app in debug mode on the Mac either. I highly recommend keeping the project in Windows if you need a Winforms app. For our example today, I’m going to choose Web and API.

The next choice you must make is which ORM to use. XPO is an excellent system, but it shines best when you use the visual designer for the database creation. Unfortunately, this designer is not ARM compatible, and I have never been able to get it to run on Windows being virtualized from my Mac. Dev Express has begun pushing EF Core as the ORM of choice for XAF in recent years, and it works great on a Mac. Additionally, when working in code only, it becomes easier to apply rules and settings to your model using attributes, and this lightens the load of what needs to be done by the model designer later.

For this example, we will choose EF Core as our ORM.

The next screen will ask about authentication and how to structure your app. If you choose to do an API and Blazor app, you must specify if you want to have separate projects or combine them in a single project. Some of the more complex apps I have built on XAF support multiple user types, and having separate APIs authentically different user types is a huge advantage. In this project today, let’s go with a single integrated project.

When it comes to authentication, It’s helpful to think ahead. If your app ever needs to authenticate users, start by enabling authentication. It’s a pain in the but to do later. You can easily add providers for OAuth and Windows Auth at a later time, but you want the security system to be preconfigured if possible.

Finally, you will select the modules you want to add. Then click next and let Visual Studio generate the project.

Next, open Nuget Manager for the project and update any out-of-date packages in the template from the Azure Libraries or the libs for EF Core. I would also recommend updating the Swagger Libraries and the JWT Library. Don’t change the major versions, but take minor and revision updates.

At that point, you can close Visual Studio and save the project. Then, we’ll head back to MacOS to do some work.

Additional Namespaces

Right off the bat, let’s open the module project and add a directory called constants to the project root. We will create four new static classes inside that folder: [NavigationGroups, Settings, SmartTypes, SecurityRoles]. These classes will contain constants for values that won’t change in our app. We might add more files later, but we need this to get started. If you’re not using authentication, you can drop the SecurityRoles class.

Next, let’s add another root directory called DataAccess. We’ll move our DB Context file into this folder and then use Rider to separate it into individual files. Rider makes it very easy and quick to accomplish this task. Move the cursor onto the class definition, hit [option + return] on your keyboard, and then use the arrow keys to move types for the whole file in a single command.

Finally, update the namespaces to use the new directory location. This can also be done in a single command for the entire folder. Rider does save us a ton of time as a developer.

Switch to MySQL and configure connection strings.

The next step in our preparations is configuring the project to connect to MySQL instead of the default MSSQL. That’s not to say you can’t use Microsft SQL Server on a Mac. You absolutely can, and it’s relatively easy to get it up and running with a Docker instance, but MSSQL is not free, and MySQL is.

Start by adding a reference to Pomelo.EntityFrameworkCore.MySql in your module project. While working with the Nuget Packages, you might as well add a reference to Microsoft.EntityFrameworkCore.Tools. We’ll need it a few steps from now.

Now jump to the Blazor project and edit the appsettings.json file. We must adjust the ConnectionString value to be a MySQL connection string. We can also clean up the file by removing comments and the EasyTest ConnectionString.

Next, please return to the module project and add a new constant to our Settings class in the Constants directory. We’ll call it CONN_STR and set it to the same connection string.

Once you’ve completed that task, it’s time to set up our DB Contexts to use the connection string during design time. Find the MyProjectContextInitializer and change the UseSqlServer line to now use MySql:

As stated in the comments for this file, it will be used for design time features only, and thus, it does not need an actual connection string.

Next, we’ll jump over to the DesignTimeContextFactory and remove the exception thrown on line 7. We’ll then uncomment the remaining code and adjust the connection to MySQL instead of SQL Server. This connection will need an actual connection string, so we’ll use the one we added to the constants file.

To wrap it up, let’s head back to the Startup class in our Blazor project and modify the code that sets up our Object Spaces.

We’ll start with some housekeeping. Let’s delete the comments on lines 76 – 79 and the EASYTEST code on Lines 84-88 and 100 – 104. In this example, I added the Audit Module, giving us two contexts. If you did not add the Audit Module to your project, then you might not see two sections here.

Finally, change the UseSqlServer to UseMySql. When you’re done, it should look like this:

Using Module Info

Since we’re using EF Core, we’ll take advantage of migrations, and when we deploy this application, we’ll generate SQL scripts from those migrations. Data Seeding can be done through a migration, but I recommend allowing the XAF Application to handle this through database updates.

We don’t want to update the seeded data every time the application runs, so we’ll configure the application to use ModuleVersioning to decide when to update. To start, we’ll need to enable the table in our DBContext. Uncomment the line that adds the DBSet for the ModulesInfo Table.

Then, let’s go to our Application class in the Blazor Project and modify the line that sets the CheckCompatibilityType in the constructor to ModuleInfo.

public MyProjectBlazorApplication() {
        ApplicationName = "MyProject";
        CheckCompatibilityType = DevExpress.ExpressApp.CheckCompatibilityType.ModuleInfo;
        DatabaseVersionMismatch += MyProjectBlazorApplication_DatabaseVersionMismatch;
    }

We’ll also want to change the code that checks for this. By default, XAF is set up only to make changes for us in Debug Mode. I prefer to let it handle these data changes in production as well. To facilitate that, you’ll need to remove the compiler instructions from around the checks and modify the code. When you’re done, it should look like this.

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.ApplicationBuilder;
using DevExpress.ExpressApp.Blazor;
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp.Security.ClientServer;
using DevExpress.ExpressApp.SystemModule;
using MyProject.Module.BusinessObjects;
using Microsoft.EntityFrameworkCore;
using DevExpress.ExpressApp.EFCore;
using DevExpress.EntityFrameworkCore.Security;

namespace MyProject.Blazor.Server;

public class MyProjectBlazorApplication : BlazorApplication {
    public MyProjectBlazorApplication() {
        ApplicationName = "MyProject";
        CheckCompatibilityType = DevExpress.ExpressApp.CheckCompatibilityType.ModuleInfo;
        DatabaseVersionMismatch += MyProjectBlazorApplication_DatabaseVersionMismatch;
    }
    protected override void OnSetupStarted() {
        base.OnSetupStarted();

        if( CheckCompatibilityType == CheckCompatibilityType.ModuleInfo) {
            DatabaseUpdateMode = DatabaseUpdateMode.UpdateDatabaseAlways;
        }

    }
    private void MyProjectBlazorApplication_DatabaseVersionMismatch(object sender, DatabaseVersionMismatchEventArgs e) {

        e.Updater.Update();
        e.Handled = true;

    }
}

That’s it; you can now generate your first migration and update your local database. Then, your application should start and have login enabled by default.
In my next article, I will walk you through setting up security in code and using one of my publicly available libraries to simplify Security Configuration. Until then, stay crafty.

Leave a Reply

Your email address will not be published. Required fields are marked *