Home > Back-end >  Entity Framework Core in .NET MAUI/Xamarin.Forms
Entity Framework Core in .NET MAUI/Xamarin.Forms

Time:06-15

I finished coding my .NET MAUI application and everything was working fine in debug mode. All my data persistence needs were being met by Entity Framework Core for Xamarin, even though I am using it on .NET MAUI.

I have made the apk file and was testing it to see if everything was okay, but turns out the database is not being created. My application crashes once I attempt to do database operations. So I am not sure if it is incompatibility of EF Core with .NET MAUI (but it was working fine in debug) or there is something I missed.

I followed the tutorial accessed here https://docs.microsoft.com/en-us/ef/core/get-started/xamarin And below is my DataContext file

DataContext.cs

using Microsoft.EntityFrameworkCore;
using MedbaseRec.Models;

namespace MedbaseRec.Utils
{
    public class DataContext : DbContext
    {
        public DbSet<QuestionPack> QuestionPacks { get; set; }
        public DbSet<Question> Questions { get; set; }

        public DataContext()
        {
            SQLitePCL.Batteries_V2.Init();

            Database.EnsureCreated();
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            string dbPath = Path.Combine(FileSystem.AppDataDirectory, "medbaseapplica.db3");
            optionsBuilder.UseSqlite($"Filename={dbPath}");
        }
    }
}

CodePudding user response:

The Android/iOS linkers are removing chunks of the Entity Framework Core / Sqlite assemblies due to the heavy use of reflection. You can instruct the linker to keep some of the important Entity Framework Core stuff like so:

  1. Add an XML file named Linker.xml to your Android project.
  2. Right click Linker.xml in your Solution Explorer then select Properties.
  3. Change Build Action to LinkDescription.
  4. Add the following XML:
<?xml version="1.0" encoding="utf-8" ?>
<linker>
    <!-- Entity Framework Core -->
    <assembly fullname="mscorlib">
        <type fullname="System.String">
            <method name="Compare"></method>
            <method name="CompareTo"></method>
            <method name="ToUpper"></method>
            <method name="ToLower"></method>
        </type>
    </assembly>
    <assembly fullname="System.Core" />
    <assembly fullname="Microsoft.EntityFrameworkCore" />
    <assembly fullname="Microsoft.EntityFrameworkCore.Sqlite" />
    <assembly fullname="Microsoft.EntityFrameworkCore.Relational" />
    <assembly fullname="SQLitePCLRaw.core" />
    <assembly fullname="SQLitePCLRaw.batteries_v2" />
    <assembly fullname="SQLitePCLRaw.lib.e_sqlite3.android" />
</linker>

The iOS linker is different and it removes some attributes Entity Framework depends on. You need to add an iOS-specific linker extension in that case:

<?xml version="1.0" encoding="utf-8" ?>
<linker>
    <!-- Entity Framework Core -->
    <assembly fullname="mscorlib">
        <type fullname="System.String">
            <method name="Compare"></method>
            <method name="CompareTo"></method>
            <method name="ToUpper"></method>
            <method name="ToLower"></method>
        </type>
        <type fullname="System.Reflection.AssemblyInformationalVersionAttribute" preserve="all" />
    </assembly>
    <assembly fullname="System.Core" />
    <assembly fullname="Microsoft.EntityFrameworkCore" />
    <assembly fullname="Microsoft.EntityFrameworkCore.Sqlite" />
    <assembly fullname="Microsoft.EntityFrameworkCore.Relational" />
    <assembly fullname="SQLitePCLRaw.core" />
    <assembly fullname="SQLitePCLRaw.batteries_v2" />
    <assembly fullname="SQLitePCLRaw.lib.e_sqlite3.ios" />
</linker>

This has been verified to work against Microsoft.EntityFrameworkCore.Sqlite version 5.0.17.

The LinkDescription XML files are documented here.

CodePudding user response:

The problem was with the Linker that thought that my EntityFrameworkCore dependency is not needed. It was working a bit too well.

I switched it off in the csproj file as follows

    <PropertyGroup>
        <AndroidLinkMode>None</AndroidLinkMode>
    </PropertyGroup>

I do think however that I should have used <AndroidLinkSkip>Assembly1</AndroidLinkSkip> to make sure that the assembly would be skipped by the linker and included in the release build.

Here is a linker to the Xamarin linker page that relates to .NET MAUI too. https://docs.microsoft.com/en-us/xamarin/android/deploy-test/linker

  • Related