12

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://learn.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}");
        }
    }
}

Tanaka Mawere
  • 683
  • 1
  • 9
  • 22
  • If you are using Code First make sure you use Database.Migrate() or Database.MigrateAsync() instead of Database.EnsureCreated(), so all your migrations can be applied. – Nikola Develops Jun 13 '22 at 07:22
  • After doing my own research, the problem has to do with the Linker. it's' removing the ```EntityFrameworkCore``` package. Or at least I think so – Tanaka Mawere Jun 14 '22 at 05:52

2 Answers2

14

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.

Trevor Balcom
  • 3,766
  • 2
  • 32
  • 51
  • which option do you have to have on the libraries linking? sdk only? if i recall correctly the dont link option will make the app be rejected? – ScottexBoy Aug 04 '22 at 09:35
1

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://learn.microsoft.com/en-us/xamarin/android/deploy-test/linker

Tanaka Mawere
  • 683
  • 1
  • 9
  • 22