无法创建类型为“ApplicationDbContext”的对象。 EF 核心 5.0

时间:2021-06-09 15:39:48

标签: c# entity-framework windows-forms-core

我使用 CleanArchitecture 解决方案。我有 ApplicationDbContext 和 UnitOfWork 所在的数据层:

namespace Portal.Data.MyDbContexts
{
    internal class ApplicationDbContext : DbContext
    {

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
        {
            Database.EnsureCreated();
        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.ApplyConfigurationsFromAssembly(typeof(BaseEntity).Assembly);
        }


        // **********
        public DbSet<WebsiteMonitoredCategory> WebsiteMonitoredCategories { get; set; }
        // **********


        
    }

工作单元:

public abstract class BaseUnitOfWork : object, IBaseUnitOfWork
    {
        //public UnitOfWork() : base()
        //{
        //}

        public BaseUnitOfWork(Options options) : base()
        {
            Options = options;
        }

        // **********
        protected Options Options { get; set; }
        // **********

        // **********
        // **********
        // **********
        private ApplicationDbContext _databaseContext;
        // **********

        // **********
        /// <summary>
        /// Lazy Loading = Lazy Initialization
        /// </summary>
        internal ApplicationDbContext DatabaseContext
        {
            get
            {
                if (_databaseContext == null)
                {
                    var optionsBuilder =
                        new DbContextOptionsBuilder<ApplicationDbContext>();

                    switch (Options.Provider)
                    {
                        case Provider.SqlServer:
                            {
                                optionsBuilder.UseSqlServer
                                    (connectionString: Options.ConnectionString);

                                break;
                            }

                        case Provider.MySql:
                            {
                                //optionsBuilder.UseMySql
                                //  (connectionString: Options.ConnectionString);

                                break;
                            }

                        case Provider.Oracle:
                            {
                                //optionsBuilder.UseOracle
                                //  (connectionString: Options.ConnectionString);

                                break;
                            }

                        case Provider.PostgreSQL:
                            {
                                //optionsBuilder.UsePostgreSQL
                                //  (connectionString: Options.ConnectionString);

                                break;
                            }

                        case Provider.InMemory:
                            {
                                optionsBuilder.UseInMemoryDatabase(databaseName: "Temp");

                                break;
                            }

                        default:
                            {
                                break;
                            }
                    }

                    _databaseContext =
                        new ApplicationDbContext(options: optionsBuilder.Options);
                }

                return _databaseContext;
            }
        }

而且我也有 IoC 层用于对表示层的依赖注入:

public class DependencyContainer
    {
        public static void RegisterServices(IServiceCollection services,IConfiguration configuration)
        {

            
            //DataLayer
            services.AddTransient<IUnitOfWork, UnitOfWork>(_ =>
            {
                Options options =
                    new Options
                    {
                        Provider =
                            (Provider)System.Convert.ToInt32(configuration.GetSection(key: "DatabaseProvider").Value),

                    

                        ConnectionString =
                            configuration.GetSection(key: "ConnectionStrings").GetSection(key: "MyConnectionString").Value,
                    };

                return new UnitOfWork(options: options);
            });


        }
    }

最后我有一个 Windows 窗体应用程序 Net 5.0(所有项目都是 Net5.0)

namespace Portal.Desktop
{
    public static class Program
    {
        private static IConfiguration Configuration { get; set; }
        public static IServiceProvider ServiceProvider { get; set; }
        /// <summary>
        ///  The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            var services = ConfigureServices();

            var builder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
            Configuration = builder.Build();

            
        

            Application.SetHighDpiMode(HighDpiMode.SystemAware);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
            RegisterServices(services, Configuration);
        }

        public static void RegisterServices(IServiceCollection services, IConfiguration configuration)
        {
            DependencyContainer.RegisterServices(services, configuration);
        }

        public static IServiceCollection ConfigureServices()
        {
            var services = new ServiceCollection();
            //services.AddTransient<IUnitOfWork, UnitOfWork>(_ =>
            //{
            //  Options options =
            //      new Options
            //      {
            //          Provider =
            //              (Provider)System.Convert.ToInt32(Configuration.GetSection(key: "DatabaseProvider").Value),

            //          //using Microsoft.EntityFrameworkCore;
            //          //ConnectionString =
            //          //  Configuration.GetConnectionString().GetSection(key: "MyConnectionString").Value,

            //          ConnectionString =
            //              Configuration.GetSection(key: "ConnectionStrings").GetSection(key: "MyConnectionString").Value,
            //      };

            //  return new Portal.Data.UoW.UnitOfWork(options: options);
            //});


            ServiceProvider = services.BuildServiceProvider();

            return services;
        }
    }
}

我使用 Ef core 5.0 ,windows 窗体设置为启动项目,包管理器控制台设置为 Protal.Data(dbcontext 和 unitofwork 在那里) 但是当我在 PMC 中运行 Add-Migration inti 时出现错误:

<块引用>

无法创建类型为“ApplicationDbContext”的对象。为了 设计时支持的不同模式,请参阅 https://go.microsoft.com/fwlink/?linkid=851728

在数据层安装这个包:

<ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.7" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.7">
        <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="5.0.7" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.7" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.7">
        <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

我不知道为什么,让我知道错误。

-----更新----

我遵循 https://go.microsoft.com/fwlink/?linkid=851728 并将 ApplicationDbContextFactory.cs 添加到 Portal.Desktop(Windows 窗体 Net5.0)项目:

namespace Portal.Desktop
{
    public class ApplicationDbContextFactory:IDesignTimeDbContextFactory<ApplicationDbContext>
    {
        public ApplicationDbContext CreateDbContext(string[] args)
        {
            var connectionString = Program.Configuration.GetSection(key: "ConnectionStrings").GetSection(key: "MyConnectionString").Value;
            var provider = Program.Configuration.GetSection(key: "DatabaseProvider").Value;
            var optionsBuilder =
                new DbContextOptionsBuilder<ApplicationDbContext>();
            var options =
                new Options
                {
                    Provider =
                        (Provider)System.Convert.ToInt32(provider),

                    //using Microsoft.EntityFrameworkCore;
                    //ConnectionString =
                    //  Configuration.GetConnectionString().GetSection(key: "MyConnectionString").Value,

                    ConnectionString = connectionString,
                };
            switch (options.Provider)
            {
                case Provider.SqlServer:
                {
                    optionsBuilder.UseSqlServer
                        (connectionString: options.ConnectionString);

                    break;
                }

                case Provider.MySql:
                {
                    //optionsBuilder.UseMySql
                    //  (connectionString: Options.ConnectionString);

                    break;
                }

                case Provider.Oracle:
                {
                    //optionsBuilder.UseOracle
                    //  (connectionString: Options.ConnectionString);

                    break;
                }

                case Provider.PostgreSQL:
                {
                    //optionsBuilder.UsePostgreSQL
                    //  (connectionString: Options.ConnectionString);

                    break;
                }

                case Provider.InMemory:
                {
                    optionsBuilder.UseInMemoryDatabase(databaseName: "Temp");

                    break;
                }

                default:
                {
                    break;
                }
            }

            return 
                new ApplicationDbContext(options: optionsBuilder.Options);
        }
    }
}

当我想添加迁移 ef core throw 异常已被调用的目标抛出。 异常:

<块引用>

System.Reflection.TargetInvocationException:已抛出异常 通过调用的目标。 ---> System.NullReferenceException: 你调用的对象是空的。在 Portal.Desktop.ApplicationDbContextFactory.CreateDbContext(String[] args) 在 C:\Users\Arman Es\source\repos\Spider\Portal.Desktop\ApplicationDbContextFactory.cs:line 20 --- 内部异常堆栈跟踪结束 --- 在 System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] 参数、签名 sig、布尔构造函数、布尔 wrapExceptions) 在 System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr、Binder 绑定器、Object[] 参数、CultureInfo 文化)
在 System.Reflection.MethodBase.Invoke(Object obj, Object[] 参数)在 Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContextFromFactory(类型 工厂,类型 contextType) 在 Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_2.b__9() 在 Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func1 factory) 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_01.b__0() 在 Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action) 调用的目标已抛出异常。

1 个答案:

答案 0 :(得分:0)

最后,我在这篇文章中找到了答案https://snede.net/you-dont-need-a-idesigntimedbcontextfactory/

在 Portal.Data 项目中创建 ApplicationDbContextFactory

using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using Portal.Domain.Tools;
using Portal.Domain.Tools.Enums;

namespace Portal.Data.MyDbContexts
{
    public class ApplicationDbContextFactory:IDesignTimeDbContextFactory<ApplicationDbContext>
    {
        private IConfiguration Configuration { get; set; }

        public ApplicationDbContext CreateDbContext(string[] args)
        {

            var builder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json");
            Configuration = builder.Build();

            var optionsBuilder =
                new DbContextOptionsBuilder<ApplicationDbContext>();
            var options =
                new Options
                {
                    Provider =
                        (Provider)System.Convert.ToInt32(Configuration.GetSection(key: "DatabaseProvider").Value),
                    ConnectionString = Configuration.GetSection(key: "ConnectionStrings").GetSection(key: "MyConnectionString").Value
                };

            switch (options.Provider)
            {
                case Provider.SqlServer:
                {
                    optionsBuilder.UseSqlServer
                        (connectionString: options.ConnectionString);

                    break;
                }

                case Provider.MySql:
                {
                    //optionsBuilder.UseMySql
                    //  (connectionString: Options.ConnectionString);

                    break;
                }

                case Provider.Oracle:
                {
                    //optionsBuilder.UseOracle
                    //  (connectionString: Options.ConnectionString);

                    break;
                }

                case Provider.PostgreSQL:
                {
                    //optionsBuilder.UsePostgreSQL
                    //  (connectionString: Options.ConnectionString);

                    break;
                }

                case Provider.InMemory:
                {
                    optionsBuilder.UseInMemoryDatabase(databaseName: "Temp");

                    break;
                }

                default:
                {
                    break;
                }
            }

            return 
                new ApplicationDbContext(options: optionsBuilder.Options);
        }
    }
}

appsettings.json 仍在 Portal.Desktop 项目中:

namespace Portal.Desktop
{
    public static class Program
    {
        public  static IConfiguration Configuration { get; set; }
        public static IServiceProvider ServiceProvider { get; set; }
        /// <summary>
        ///  The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            var services = ConfigureServices();

            RegisterServices(services, Configuration);


            Application.SetHighDpiMode(HighDpiMode.SystemAware);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
            
        }

        public static void RegisterServices(IServiceCollection services, IConfiguration configuration)
        {
            DependencyContainer.RegisterServices(services, configuration);
        }

        public static IServiceCollection ConfigureServices()
        {
            var services = new ServiceCollection();
            

            ServiceProvider = services.BuildServiceProvider();

            return services;
        }
    }
}

最后IoC项目是:

namespace Portal.IoC
{
    public class DependencyContainer
    {
        public static void RegisterServices(IServiceCollection services,IConfiguration configuration)
        {

            //DataLayer
            services.AddTransient<IUnitOfWork, UnitOfWork>(_ =>
            {
                var options =
                    new Options
                    {
                        Provider =
                            (Provider)System.Convert.ToInt32(configuration.GetSection(key: "DatabaseProvider").Value),
                        ConnectionString =
                            configuration.GetSection(key: "ConnectionStrings").GetSection(key: "MyConnectionString").Value,
                    };

                return new UnitOfWork(options: options);
            });

        


        }
    }
}