Unable to create an object of type 'LightContext'. Add an implementation of 'IDesignTimeDbContextFactory<LightContext>' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time.
这个问题如果是在Web项目,并且配置了DbContext的链接字符串的话,是不会出现此问题的。很显然是迁移命令没有找到DbConnectionString导致的,接下来我们按照提示,实现一个IDesignTimeDbContextFactory<LightContext>试试
解决方法:
创建一个与DbContext同一目录下的DesignTimeDbContextFactory文件,然后实现接口中的方法CreateDbContext,并配置ConnectionString
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<LightContext> { public LightContext CreateDbContext(string[] args) { var builder = new DbContextOptionsBuilder<LightContext>(); builder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Integrated Security=true;Initial Catalog=Light;"); return new LightContext(builder.Options); } }
再次执行迁移命令,终于成功了。
成功提示:
Done. To undo this action, use 'ef migrations remove'
同时类库下面会生成Migrations文件夹以及相关的迁移文件
2、小试迁移命令
a)、使用以下命令应用迁移,生成数据库和表
dotnet ef database update
通过VS的SQL Server资源管理器查看生成数据库的结构,其中__EFMigrationsHistory为每次迁移的记录表
b)、因为string类型的字段迁移到数据库之后的数据类型为nvarchar(max)并且是可空类型的,下面我们就使用Fluent API对ApplicationUser表字段进行配置,同样你也可以使用属性注解的方式进行配置,因为我自己不喜欢“污染”表实体
public static void ConfigApplicationUser(ModelBuilder modelBuilder) { modelBuilder.Entity<ApplicationUser>(m => { m.Property(t => t.Email) .HasMaxLength(50); m.Property(t => t.UserName) .IsRequired() .HasMaxLength(50); m.Property(t => t.Password) .IsRequired() .HasMaxLength(20); }); }
然后同样使用上面的两条命令重新迁移并更新数据库结构
观察数据库表结构已经更新
同理添加字段,删除字段都是一样的迁移操作,还是很方便的
3、扩展
a)、为了方便演示,其实上面在类库中执行迁移时的数据库连接字符串是写死的,那么最好的办法是应该去读取Web项目下已经配置好的连接,这样就能保证上下的一致性,不用再去为了EF的迁移而单独维护一个多余的数据库连接配置。改造也很简单,即通过Configuration组件读取appsettings.json的ConnectionStrings节点,改造之后是这样子的:
public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<LightContext> { public LightContext CreateDbContext(string[] args) { Directory.SetCurrentDirectory("..");//设置当前路径为当前解决方案的路径 string appSettingBasePath = Directory.GetCurrentDirectory() + "/Light.AuthorityApi";//改成你的appsettings.json所在的项目名称 var configBuilder = new ConfigurationBuilder() .SetBasePath(appSettingBasePath) .AddJsonFile("appsettings.json") .Build(); var builder = new DbContextOptionsBuilder<LightContext>(); //builder.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Integrated Security=true;Initial Catalog=Light;"); builder.UseSqlServer(configBuilder.GetConnectionString("LightConnection")); return new LightContext(builder.Options); } }
注意需要额外引入下面这个Nuget包:
Install-Package Microsoft.Extensions.Configuration.Json
b)、属性注解[Column(Order = 1)]对EF Core来说还没有达到可以调整数据库生成字段的顺序,不过我们还是可以修改迁移文件的实体属性的顺序来达到我们想要的效果。下面是我调整之后重新生成的表,是不是看出来和上面的有什么不同,一图胜万语:
c)、最后一步,自己动手试试看:创建一个SeedData迁移文件来添加数据库的初始数据。:)