我使用 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 forms 设置为启动项目,包管理器控制台设置为 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 forms 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);
}
}
}
当我想添加迁移时,核心抛出异常已被调用的目标抛出。例外:
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[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfoculture )
在 System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) 在 Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContextFromFactory(Type factory, Type contextType) 在 Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_2 .b__9() at 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_0
1.b__0() at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action) 调用的目标已引发异常。