dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.5k stars 3.13k forks source link

.NET 8 migration on .NET MAUI Blazor Hybrid App causes exception: The type initializer for "<Module>" threw an exception. #32384

Open Ccry11 opened 7 months ago

Ccry11 commented 7 months ago

.NET 8 migration on .NET MAUI Blazor Hybrid App causes exception Unable to create a 'DbContext' of type 'ApplicationDbContext'. The exception 'The type initializer for '<Module>' threw an exception.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

My code

ApplicationDbContext.cs

using MauiApp1.Model;
using Microsoft.EntityFrameworkCore;
using System.Reflection;

namespace MauiApp1.Context
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext() { }
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> contextOptions)
            : base(contextOptions)
        {
        }

        public DbSet<Person> People { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
        }
    }
}

MauiProgram.cs

using MauiApp1.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace MauiApp1
{
    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                });

            builder.Services.AddMauiBlazorWebView();

#if DEBUG
            builder.Services.AddBlazorWebViewDeveloperTools();
            builder.Logging.AddDebug();
#endif

            builder.Services.AddDbContext<ApplicationDbContext>(
                options =>
                    options.UseSqlite(
                        "Data Source=C:\\Users\\USER\\Documents\\Test.db;Cache=Shared"
                    )
                );

            builder.Services.AddScoped<DbContext, ApplicationDbContext>();

            return builder.Build();
        }
    }
}

Person.cs

namespace MauiApp1.Model
{
    public class Person
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

PersonConfiguration.cs

using MauiApp1.Model;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace MauiApp1.EntityConfiguration
{
    class PersonConfiguration : IEntityTypeConfiguration<Person>
    {
        public void Configure(EntityTypeBuilder<Person> builder)
        {
            builder.HasKey(o => o.Id);
            builder.Property(t => t.FirstName).IsRequired(false);
            builder.Property(t => t.LastName).IsRequired(false);
        }
    }
}

MauiApp1.csproj

        <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0">
          <PrivateAssets>all</PrivateAssets>
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
        <PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
        <PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
        <PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="$(MauiVersion)" />
        <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />

Stack traces - Vebose output

By runing the command: dotnet ef migrations add FirstMigration --project MauiApp1 --context ApplicationDbContext --verbose the following error occurs:

Using assembly 'MauiApp1'.
Using startup assembly 'MauiApp1'.
Using application base 'C:\Users\USER\source\repos\MauiApp1\MauiApp1\bin\Debug\net8.0-windows10.0.19041.0\win10-x64'.
Using working directory 'C:\Users\USER\source\repos\MauiApp1\MauiApp1'.
Using root namespace 'MauiApp1'.
Using project directory 'C:\Users\USER\source\repos\MauiApp1\MauiApp1\'.
Remaining arguments: .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'MauiApp1'...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'ApplicationDbContext'.
Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create a 'DbContext' of type 'ApplicationDbContext'. The exception 'The type initializer for '<Module>' threw an exception.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
 ---> System.TypeInitializationException: The type initializer for '<Module>' threw an exception.
 ---> System.TypeInitializationException: The type initializer for 'WinRT.ActivationFactory`1' threw an exception.
 ---> System.Runtime.InteropServices.COMException (0x80040154): Interfaccia non registrata. (0x80040154 (REGDB_E_CLASSNOTREG))
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
   at WinRT.BaseActivationFactory..ctor(String typeNamespace, String typeFullName)
   at WinRT.ActivationFactory`1..ctor()
   at WinRT.ActivationFactory`1..cctor()
   --- End of inner exception stack trace ---
   at WinRT.ActivationFactory`1.ActivateInstance[I]()
   at Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentInitializeOptions..ctor()
   at Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManagerCS.AutoInitialize.get_Options() in C:\Users\USER\.nuget\packages\microsoft.windowsappsdk\1.3.230724000\include\DeploymentManagerAutoInitializer.cs:line 44
   at Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManagerCS.AutoInitialize.AccessWindowsAppSDK() in C:\Users\USER\.nuget\packages\microsoft.windowsappsdk\1.3.230724000\include\DeploymentManagerAutoInitializer.cs:line 30
   at .cctor()
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass20_5.<FindContextTypes>b__13()
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   --- End of inner exception stack trace ---
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Unable to create a 'DbContext' of type 'ApplicationDbContext'. The exception 'The type initializer for '<Module>' threw an exception.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

Include provider and version information

EF Core version: 8.0.0 Database provider: SqlLite Target framework: .NET 8.0 Operating system: Windows 10 22H2 Build 19045 IDE: Visual Studio 2022 17.8.1 dotnet-ef CLI: 8.0.0

wesleyscaldwell commented 7 months ago

I'm having the same issue, did you manage to find a workaround?

I tried the device factory option also, and that didn't resolve it.

No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Using DbContext factory 'DeviceContextFactory'.
Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create a 'DbContext' of type 'DeviceContext'. The exception 'The type initializer for '<Module>' threw an exception.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
 ---> System.TypeInitializationException: The type initializer for '<Module>' threw an exception.
 ---> System.TypeInitializationException: The type initializer for 'WinRT.ActivationFactory`1' threw an exception.
 ---> System.Runtime.InteropServices.COMException (0x80040154): Class not registered (0x80040154 (REGDB_E_CLASSNOTREG))
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
   at WinRT.BaseActivationFactory..ctor(String typeNamespace, String typeFullName)
   at WinRT.ActivationFactory`1..ctor()
   at WinRT.ActivationFactory`1..cctor()
   --- End of inner exception stack trace ---
   at WinRT.ActivationFactory`1.ActivateInstance[I]()
   at Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentInitializeOptions..ctor()
   at Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManagerCS.AutoInitialize.get_Options() in C:\Users\Wesley\.nuget\packages\microsoft.windowsappsdk\1.3.230724000\include\DeploymentManagerAutoInitializer.cs:line 44
   at Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManagerCS.AutoInitialize.AccessWindowsAppSDK() in C:\Users\Wesley\.nuget\packages\microsoft.windowsappsdk\1.3.230724000\include\DeploymentManagerAutoInitializer.cs:line 30
   at .cctor()
   --- End of inner exception stack trace ---
   at System.RuntimeTypeHandle.GetActivationInfo(RuntimeType rt, & pfnAllocator, Void*& vAllocatorFirstArg, & pfnCtor, Boolean& ctorIsPublic)
   at System.RuntimeType.ActivatorCache..ctor(RuntimeType rt)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContextFromFactory(Type factory, Type contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass20_3.<FindContextTypes>b__9()
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   --- End of inner exception stack trace ---
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
wesleyscaldwell commented 7 months ago

Ok, I found a work around. And i'm going to be up front and honest, I found this by luck and have no clue what it is doing or why it works.

I added this to the csproj and then it added the migration.

<WindowsAppSdkDeploymentManagerInitialize>false</WindowsAppSdkDeploymentManagerInitialize>

https://github.com/dotnet/maui/issues/12080#issuecomment-1398635826

Ccry11 commented 7 months ago

@wesleyscaldwell Thank you very much! I confirm that in this way the migration is added and then it can also be applied. I have found a comment about that property: https://github.com/microsoft/microsoft-ui-xaml/issues/8182#issuecomment-1430538408 . I hope that someone can understand why this issue occurs and propose a proper way to fix it

M-Nesti commented 6 months ago

@wesleyscaldwell : Thank you so much! Investigating this issue took me quite some time, your workaround helped! God bless you

evolcano commented 1 month ago

I have the same error during debug., and cost few days:

System.TypeInitializationException HResult=0x80131534 Message=The type initializer for 'WinRT.ActivationFactory1' threw an exception. Source=Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection StackTrace: at WinRT.ActivationFactory1.ActivateInstance[I]() at Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentInitializeOptions..ctor() at Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManagerCS.AutoInitialize.get_Options() in C:\Users\Volca.nuget\packages\microsoft.windowsappsdk\1.5.240311000\include\DeploymentManagerAutoInitializer.cs:line 44

This exception was originally thrown at this call stack: [External Code]

Inner Exception 1: COMException: Class not registered (0x80040154 (REGDB_E_CLASSNOTREG))

The error is raised form Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentInitializeOptions:

    public DeploymentInitializeOptions()
        : this(WinRT.ActivationFactory<DeploymentInitializeOptions>.ActivateInstance<IUnknownVftbl>())
    {
        ComWrappersSupport.RegisterObjectForInterface(this, ThisPtr);
        ComWrappersHelper.Init(_inner, addRefFromTrackerSource: false);
    }

Which is called by Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManagerCS.icrosoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManagerCS image

I think maybe WinRT.ActivationFactory cann't be initialized. It is said MSIX is running in a container which has some limitation in this artical, such as:

So I unchecked project pproperties of Packaging: image

Debug can go again. But I still have questions:

  1. If this is the reason of error?
  2. Why type initializer for 'WinRT.ActivationFactory` throw error?
  3. how can I use MSIX to abtain advantages?