EntityFramework works in Editor crashes when ran from a build

Hello everyone.

We are working on our database code and are PoCing EntityFramework in Unity.

The code runs in the Editor and builds for both IL2CPP and Mono 2.x, but when launching the player we get the following error.

InvalidOperationException: A suitable constructor for type 'Microsoft.EntityFrameworkCore.Internal.DbSetInitializer' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite (Microsoft.Extensions.DependencyInjection.ServiceLookup.ResultCache lifetime, System.Type serviceType, System.Type implementationType, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain callSiteChain) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact (Microsoft.Extensions.DependencyInjection.ServiceDescriptor descriptor, System.Type serviceType, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain callSiteChain, System.Int32 slot) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact (System.Type serviceType, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain callSiteChain) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite (System.Type serviceType, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain callSiteChain) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory+<>c__DisplayClass7_0.<GetCallSite>b__0 (System.Type type) [0x00000] in <00000000000000000000000000000000>:0
  at System.Func`2[T,TResult].Invoke (T arg) [0x00000] in <00000000000000000000000000000000>:0
  at System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.GetCallSite (System.Type serviceType, Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteChain callSiteChain) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.CreateServiceAccessor (System.Type serviceType) [0x00000] in <00000000000000000000000000000000>:0
  at System.Func`2[T,TResult].Invoke (T arg) [0x00000] in <00000000000000000000000000000000>:0
  at System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService (System.Type serviceType, Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope serviceProviderEngineScope) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService (System.Type serviceType) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService (System.Type serviceType) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService (System.IServiceProvider provider, System.Type serviceType) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T] (System.IServiceProvider provider) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.EntityFrameworkCore.DbContext..ctor (Microsoft.EntityFrameworkCore.DbContextOptions options) [0x00000] in <00000000000000000000000000000000>:0
  at Microsoft.EntityFrameworkCore.DbContext..ctor () [0x00000] in <00000000000000000000000000000000>:0
  at AhBearStudios.Database.SQLiteDbContext..ctor () [0x00000] in <00000000000000000000000000000000>:0
  at SampleDB.Start () [0x00000] in <00000000000000000000000000000000>:0

To recreate this issue simply import the attached package. Create a Empty Game object → Attach the SampleDB script → Build → Run

Thanks in advanced!

7979007–1024221–EntityFramework_ORM.unitypackage (1.34 MB)

It looks like it is trying to access some types/members via reflection, without there being any explicit references to them. When using IL2CPP, Unity will remove unused code, and if the code is only used through reflection, then the reflection will not be able to find it. See Unity - Manual: Managed code stripping for more details.

Tautvydas,
Thank you for your response. I will look further into the reflection issue, but this also happens when running it built against Mono 2.x which I did not think reflection was an issue when using Mono.

Appreciate the help.

It has the same limitation if stripping is enabled in player settings.

I’m facing exactly the same issue. Could you resolve it by deactivating code stripping? And if so, is it possible to work around this without changing the project settings?

I have a similar issue with IL2CPP ( InvalidOperationException: A suitable constructor for type ‘Microsoft.Extensions.Logging.LoggerFactory’ could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.)

I read through Unity - Manual: Managed code stripping. My stripping is set to Minimal, I tried the link.xml to no avail and I am looking to try the [Preserve] attribute.

I am building a 3rd party library that is creating its own logger and don’t want to depend on the Unity engine for the [Preserve] attribute. There is a link in the page that is supposed to show you how to create you own attribute that is not dependant on the Unity Engine, but the page is not available. Could someone share the link to that page or any other solution for this code stripping?

Hey @GambitMonkey

You are experience an issue related to AOT compilation code stripping. It happens because the compiler believes the class won’t be ever used that is why it simply deletes the class or some functions of a class from the compiled binary.

You can resolve the trouble by adding link.xml file and by adding specific classes, namespaces, functions you want to keep during AOT compilation even if you don’t have a reference on it in your code.

There is a sample: Unity-EFCore-SQLite/Assets/_PackageRoot/Runtime/link.xml at master · IvanMurzak/Unity-EFCore-SQLite · GitHub

OR

Instead of manual integration of EntityFrameworkCore and all the dependencies. You can use the bundle package that I made and tested on

  • Windows
  • Android
  • iOS
  • MacOS

It includes SQLite providers for each platform which works perfectly in a project with this setup

API Compatibility: .NET Standard 2.0 or 2.1
Backend: IL2CPP

The package almost doesn’t have it is own code, it is just a bundle of “right” dependencies and link.xml file to support EFCore + SQLite on mentioned platforms in player build.