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.68k stars 3.17k forks source link

Migration Generation Fails With Method Not Found Exception #32100

Closed mhdubose closed 11 months ago

mhdubose commented 11 months ago

Creating a very basic ASP.NET Core 8 application with the latest EF Core Design and tools (version 8.0.0-rc.2.23480.1). After wiring up npgsql and a simple DbContext, attempting to generate a migration from the CLI results in the below exception

using System.Reflection;
using Sample.Data;
using EntityFramework.Exceptions.PostgreSQL;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.Identity.Web;
using Npgsql;
using Serilog;
using Serilog.Events;
using Serilog.Exceptions;
using Serilog.Exceptions.Core;
using Serilog.Exceptions.EntityFrameworkCore.Destructurers;

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .CreateLogger();

try
{
    var builder = WebApplication.CreateBuilder(args);
    builder.Host.UseSerilog((context, services, configuration) => configuration
        .ReadFrom.Configuration(context.Configuration)
        .ReadFrom.Services(services)
        .Enrich.FromLogContext()
        .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder()
            .WithDefaultDestructurers()
            .WithDestructurers(new[] { new DbUpdateExceptionDestructurer() })));

    var pgDataSourceBuilder =
        new NpgsqlDataSourceBuilder(builder.Configuration.GetConnectionString("DefaultConnection"));
    pgDataSourceBuilder.UseNodaTime();
    var pgDataSource = pgDataSourceBuilder.Build();
    builder.Services.AddDbContext<DataContext>(options =>
    {
        options.UseNpgsql(pgDataSource, dbBuilder =>
        {
            dbBuilder.MigrationsAssembly(typeof(DataContext).GetTypeInfo().Assembly.GetName().Name);
            dbBuilder.UseNodaTime();
            dbBuilder.EnableRetryOnFailure();
        });
        options.UseSnakeCaseNamingConvention();
        options.UseExceptionProcessor();
    });

// Add services to the container.
    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAdB2C"));
    builder.Services.AddAuthorization();

    builder.Services.AddControllers();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();

    var app = builder.Build();

// Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI();
    }

    app.UseHttpsRedirection();

    app.UseAuthentication();
    app.UseAuthorization();
    app.MapControllers();

    app.Run();
}
catch (HostAbortedException)
{
    //Swallow expected exception from EF Core
    Log.Debug("Host aborting");
}
catch (Exception e)
{
    Log.Fatal(e, "Application Terminated Unexpectedly");
}
finally
{
    Log.CloseAndFlush();
}
using Sample.Data.Entities;
using Microsoft.EntityFrameworkCore;

namespace Sample.Data;

public class DataContext: DbContext
{
    public DataContext(DbContextOptions options) : base(options)
    {
    }

    public DbSet<User> Users => Set<User>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<User>()
            .HasIndex(u => u.Email)
            .IsUnique();
    }
}
public class User
{
    public int Id { get; set; }

    public required string FirstName { get; set; }

    public required string LastName { get; set; }

    public required string Email { get; set; }

    public string? PhoneNumber { get; set; }
}
dotnet ef migrations add "InitialMigration"
Build started...
Build succeeded.
Unable to create a 'DbContext' of type ''. The exception 'Method not found: 'System.Nullable`1<Microsoft.EntityFrameworkCore.Metadata.StoreObjectIdentifier> Microsoft.EntityFrameworkCore.Metadata.StoreObjectIdentifier.Create(Microsoft.EntityFrameworkCore.Metadata.IReadOnlyEntityType, Microsoft.EntityFrameworkCore.Metadata.StoreObjectType)'.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

Downgrading the EF Core packages and CLI tool to 7.0.12 resolves the issue, and the migration generates.

Include provider and version information

EF Core version: 8.0.0-rc.2.23480.1 Database provider: Npgsql.EntityFrameworkCore.PostgreSQL Target framework: .NET 8 RC2 Operating system: Windows 11 IDE: CLI

ErikEJ commented 11 months ago

You are maybe mixing versions - please share your csproj file.

mhdubose commented 11 months ago

Here's the proj file and my tool manifest

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <InvariantGlobalization>true</InvariantGlobalization>
        <UserSecretsId>***</UserSecretsId>
        <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="EFCore.NamingConventions" Version="7.0.2" />
        <PackageReference Include="EntityFrameworkCore.Exceptions.PostgreSQL" Version="6.0.3" />
        <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0-rc.2.23480.2"/>
        <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.0-rc.2.23480.2"/>
        <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0-rc.2.23480.2"/>
        <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0-rc.2.23480.1">
          <PrivateAssets>all</PrivateAssets>
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
        <PackageReference Include="Microsoft.Identity.Web" Version="2.15.2" />
        <PackageReference Include="Microsoft.Identity.Web.DownstreamApi" Version="2.15.2" />
        <PackageReference Include="NodaTime" Version="3.1.9" />
        <PackageReference Include="NodaTime.Serialization.SystemTextJson" Version="1.1.2" />
        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0-rc.2" />
        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="8.0.0-rc.2" />
        <PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
        <PackageReference Include="Serilog.Exceptions.EntityFrameworkCore" Version="8.4.0" />
        <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
    </ItemGroup>

    <ItemGroup>
      <Content Include="..\.dockerignore">
        <Link>.dockerignore</Link>
      </Content>
    </ItemGroup>

</Project>
{
  "version": 1,
  "isRoot": true,
  "tools": {
    "dotnet-ef": {
      "version": "8.0.0-rc.2.23480.1",
      "commands": [
        "dotnet-ef"
      ]
    }
  }
}
roji commented 11 months ago

@mhdubose you cannot mix EFCore.NamingConventions 7.0.2 with EF 8.0.0-rc.2. You'll have to wait for that plugin to be updated for 8.0.0.

mhdubose commented 11 months ago

Ah, that's the offending dependency. I thought I had tested removing it, but I guess I missed it. Thanks @roji