WPF с платформой сущностей на ядре net - невозможно создать объект типа AppDbContext - PullRequest
1 голос
/ 10 февраля 2020

У меня есть простое WPF Net Базовое приложение, когда я использую Entity Framework, у меня есть DbContext, но когда я добавляю миграцию, я получаю ошибку:

PM> add-migration init
Build started...
Build succeeded.
Unable to create an object of type 'AppDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

мои настройки приложения. json

{
  "ConnectionStrings": {
    "SqlConnection": "Server=DESKTOP-K6R1EB3\\tester;Database=test;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

AppDbContext

using Microsoft.EntityFrameworkCore;

namespace WpfApp1
{
    public class AppDbContext : DbContext
    {
        public DbSet<Person> Person { get; set; }
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
        {

        }


    }
}

App.xaml.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using System.Windows;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public IServiceProvider ServiceProvider { get; private set; }

        public IConfiguration Configuration { get; private set; }

        protected override void OnStartup(StartupEventArgs e)
        {
            var builder = new ConfigurationBuilder()
             .SetBasePath(Directory.GetCurrentDirectory())
             .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

            Configuration = builder.Build();

            var serviceCollection = new ServiceCollection();
            ConfigureServices(serviceCollection);

            ServiceProvider = serviceCollection.BuildServiceProvider();

            var mainWindow = ServiceProvider.GetRequiredService<MainWindow>();
            mainWindow.Show();
        }

        private void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<AppDbContext>
        (options => options.UseSqlServer(
                    Configuration.GetConnectionString("SqlConnection")));

            services.AddTransient(typeof(MainWindow));
        }
    }
}

Конечно, у меня есть простая модель для базы данных

namespace WpfApp1
{
    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
    }
}

Что не так? Я ищу решение, но ничего не нашел. Раньше я писал веб-приложение в ядре и структуре сущностей net, и у меня нет никаких проблем. Это мое первое приложение WPF Net Core, и у меня проблема с настройкой EF.

1 Ответ

2 голосов
/ 10 февраля 2020

Я смог воспроизвести вашу проблему и преодолеть ее.

Я сталкивался с этим раньше. эта статья рассказала мне о том, что мне нужно было сделать, очень благодарна за это: https://blog.tonysneed.com/2018/12/20/idesigntimedbcontextfactory-and-dependency-injection-a-love-story/

из статьи в сообщении об ошибке: https://go.microsoft.com/fwlink/?linkid=851728. в частности, в этом разделе https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dbcontext-creation#from -a-design-time-factory мы можем использовать некоторую типизацию утки и предоставить класс, который Microsoft.EntityFrameworkCore.Tools будет использовать для создания миграций, реализуя IDesignTimeDbContextFactory<T>.

В статье Тони Снида дается обобщенная c абстрактная реализация, которую мы можем затем вывести очень просто.

вот обобщенная c абстрактная реализация (отредактируйте, извините, только что понял, я копирую- вставил мою адаптацию кода Тони Снида, который я использовал, когда сталкивался с этим раньше):

public abstract class DesignTimeDbContextFactoryBase<TContext> : IDesignTimeDbContextFactory<TContext> where TContext : DbContext
{
    public TContext CreateDbContext(string[] args)
    {
        return Create(Directory.GetCurrentDirectory(), Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));
    }
    protected abstract TContext CreateNewInstance(DbContextOptions<TContext> options);
    public TContext Create()
    {
        var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        var basePath = AppContext.BaseDirectory;
        return Create(basePath, environmentName);
    }
    TContext Create(string basePath, string environmentName)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(basePath)
            .AddJsonFile("appsettings.json")
            .AddJsonFile($"appsettings.{environmentName}.json", true)
            .AddEnvironmentVariables();
        var config = builder.Build();
        var connstr = config.GetConnectionString("default");
        if (string.IsNullOrWhiteSpace(connstr) == true)
            throw new InvalidOperationException("Could not find a connection string named 'default'.");
        return Create(connstr);
    }
    TContext Create(string connectionString)
    {
        if (string.IsNullOrEmpty(connectionString))
            throw new ArgumentException($"{nameof(connectionString)} is null or empty.", nameof(connectionString));
        var optionsBuilder = new DbContextOptionsBuilder<TContext>();
        Console.WriteLine($"MyDesignTimeDbContextFactory.Create(string): Connection string: {connectionString}");
        optionsBuilder.UseSqlServer(connectionString, s => s.CommandTimeout((int)TimeSpan.FromMinutes(10).TotalSeconds));
        DbContextOptions<TContext> options = optionsBuilder.Options;
        return CreateNewInstance(options);
    }
}

вы предоставляете реализацию для AppDbContext:

public class AppDbContextFactory : DesignTimeDbContextFactoryBase<AppDbContext>
{
    protected override AppDbContext CreateNewInstance(DbContextOptions<AppDbContext> options)
    {
        return new AppDbContext(options);
    }
}

, что Add-Migration ( или, возможно, технически Microsoft.EntityFrameworkCore.Tools) обнаружит.

было добавлено много пакетов nuget:

<ItemGroup>
  <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.1" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.1" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.1">
    <PrivateAssets>all</PrivateAssets>
    <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  </PackageReference>
  <PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.1" />
  <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.1" />
  <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.1" />
  <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.1" />
</ItemGroup>

как только вы преодолеете свою ошибку, я получил еще один: Could not find a connection string named 'default'., поэтому я изменил настройки приложения SqlConnection на default.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...