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:
- Add an XML file named Linker.xml to your Android project.
- Right click Linker.xml in your Solution Explorer then select Properties.
- Change Build Action to LinkDescription.
- 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