EntityFrameworkCore v1.1.1 问题汇总

随着宇宙第一IDE的最新版本发布[2017/3/7],AspNetCore 和EntityFrameworkCore(团队)都发布了最新的代码。Red rose程序员

不过在我看来,这些到还不是最重要的。最重要的是dotnet cli终于rtm了,以及和它配套的各种工具。好鸡冻啊,终于不用管beta,preview,final,final-update之类的版本了。虽然从此必定还会有各种版本发布,可是本次发布以后,工具的不少使用方式和习惯都会定下来(一些),方便咱们这种用户使用和记忆。sql

image

问题环境

为了跟进新本版,在安装了vs2017以后,我就火烧眉毛地搭建了一个项目进行测试。数据库

image

项目json

内容mvc

EfCore11.Domain Entity类型,不须要引用其余nuget包
EfCore11.DataSqlServer DbContext项目,须要引用Microsoft.EntityFrameworkCore.SqlServer等nuget包
EfCore11.SomeUI AspnetCore MVC项目,能够经过dotnet new mvc命令生成

其中的项目文件:oracle

Domain项目中的Blog.cs文件app

  1 using System.Collections.Generic;
  2 
  3 namespace EfCore11.Domain
  4 {
  5     public class Blog
  6     {
  7         public int Id { get; set; }
  8         public string Name { get; set; }
  9         public string Url { get; set; }
 10         public ICollection<Post> Posts { get; set; }
 11     }
 12 }
 13 

Domain项目中的Post.cs文件less

  1 namespace EfCore11.Domain
  2 {
  3     public class Post
  4     {
  5         public int Id { get; set; }
  6         public string Title { get; set; }
  7         public string Body { get; set; }
  8 
  9         public int BlogId { get; set; }
 10         public Blog Blog { get; set; }
 11     }
 12 }
 13 

DataSqlServer项目中的BlogDbContext.cs文件ide

  1 using EfCore11.Domain;
  2 using Microsoft.EntityFrameworkCore;
  3 
  4 namespace EfCore11.DataSqlServer
  5 {
  6     public class BlogDbContext : DbContext
  7     {
  8         public DbSet<Post> Post { get; set; }
  9         public DbSet<Blog> Blog { get; set; }
 10 
 11         public BlogDbContext(DbContextOptions<BlogDbContext> option)
 12             : base(option)
 13         {
 14 
 15         }
 16     }
 17 }

SomeUI项目中Startup.cs文件中修改的代码工具

  1 public void ConfigureServices(IServiceCollection services)
  2 {
  3     // Add framework services.
  4     services.AddMvc();
  5     // 此处不用json配置的方法了,由于不是本文的重点。若有须要请自行baidu
  6     string conn = "server=(localdb)\\mssqllocaldb;database=Ef.Core;Trusted_connection=true;";
  7     services.AddDbContext<BlogDbContext>(opt => opt.UseSqlServer(conn));
  8 }

问题0:在哪一个项目上执行 code first migration 呢?

按照如今的项目机构,能够执行code first migration 的项目有两个:分别是DbContext项目,也就是本文环境中的DataSqlServer项目;以及Mvc项目,也就是本文中的SomeUI项目。

这两个项目均可以完成数据库迁移所需的操做,可是实现目有所不一样。由于在哪一个项目内完成迁移就意味着要由哪一个项目中维护相应的迁移代码,而用于生产环境的MVC项目是不会包含所有数据库迁移代码的(理由不少了,谁也不会把包含“简历生成事件”的代码放到生产环境上的),因此一般状况下的开发项目采用DbContext项目管理迁移代码,测试环境随意。

 

 

先说简单的,在MVC环境下迁移:

问题1:执行 dotnet ef 命令错误

重现方法:CMD打开SomeUI目录,而后执行“dotnet ef”命令

报错内容:No executable found matching command "dotnet-ef"

问题解释:ef core编写时其内容被拆分红为了不少包,以方便程序员只加载程序所需的代码,这样程序就会占用更小的内存,运行速度更快,部署更容易。因此想要运行dotnet-ef命令,还须要加载Microsoft.EntityFrameworkCore.Tools.DotNet

此包的描述是这样的

image

处理方法:由于目前dotnet cli尚未直接添加命令行工具引用的方法,因此只能暴力一点儿了,直接修改csproj文件:

在ProjectGroup标签下直接添加:

  1   <ItemGroup>
  2     <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
  3   </ItemGroup>

//添加完毕后,若是你的vs出现了一些奇怪的现象,好比nuget包没有加载,引用不正常,能够尝试关闭当前的项目,而后从新打开项目来解决这个问题。

//看上去就是项目文件没有在修改后从新加载,但愿update1的时候可以更稳定一些。

修复检查:从新执行dotnet ef,能看到独角兽啊

image

问题2:执行 dotnet ef migrations add initial 报错

重现方法:CMD打开SomeUI目录,执行“dotnet ef migrations add initial”

报错内容:Could not load file or assembly 'Microsoft.EntityFrameworkCore.Design, Culture=neutral, PublicKeyToken=null'. 绯荤粺鎵句笉鍒版寚瀹氱殑鏂囦欢銆

问题解释:和上一个问题同样,并且错误信息也说的比较明确,就是还缺乏一个nuget包:Microsoft.EntityFrameworkCore.Design

处理方法:在cli下的添加方式是执行:dotnet add package Microsoft.EntityFrameworkCore.Design

修复检查:再次执行dotnet ef migrations add initial ,报错信息更改了:

image

问题3:迁移报错,须要指定包含迁移的程序集

重现方法:详见问题2

报错内容:Your target project 'xxxxx' doesn't match your migrations assembly xxxxxxxx'. Either change your target project or change your migrations assembly.

问题解释:当前执行迁移项目和包含DbContext程序集项目不一致,要么更改执行迁移操做的项目,要么修改迁移程序集。

处理方法:两条路本身选,要么切换到用DbContext程序集管理迁移代码,要么修改当前代码以适应迁移方法。错误信息里给出了一个简单的解决方法:

Change your migrations assembly by using DbContextOptionsBuilder. E.g. options.UseSqlServer(connection, b => b.MigrationsAssembly("EfCore11.SomeUI")). By default, the migrations assembly is the assembly containing the DbContext.
Change your target project to the migrations project by using the Package Manager Console's Default project drop-down list, or by executing "dotnet ef" from the directory containing the migrations project.

对应修改的代码是SomeUI项目的Startup.cs文件

  1 public void ConfigureServices(IServiceCollection services)
  2 {
  3     // Add framework services.
  4     services.AddMvc();
  5     // 此处不用json配置的方法了,由于不是本文的重点。若有须要请自行baidu
  6     string conn = "server=(localdb)\\mssqllocaldb;database=Ef.Core;Trusted_connection=true;";
  7     services.AddDbContext<BlogDbContext>(opt => opt.UseSqlServer(conn
  8         ,b=>b.MigrationsAssembly("EfCore11.SomeUI")
  9         ));
 10 }

修复检查:从新执行迁移命令,成功。

image

以后再执行“dotnet ef database update”就能够按照现有代码迁移,建立相应的数据库了。

至此,简单的代码迁移过程完成了。不过以上流程的解决方案不用划分为三个项目也能够实现,若是想要实现复杂项目或者用于部署身缠环境的方案,还须要过如下坑。

 

使用DbContext项目迁移:

对于环境和代码改动须要回滚到问题0。而后使用CMD打开DataSqlServer目录。

执行 dotnet ef命令,会遇到问题1,问题2的错误,根据描述进行修改便可,不过须要注意项目已经更换,不要改错地方了  :)

问题4:ef tooling 对于.NetStandard的支持问题

重现方法:CMD执行代码迁移

报错内容:Startup project 'EfCore11.DataSqlServer.csproj' targets framework '.NETStandard'. This framework is not intended for execution and may fail to resolve runtime dependencies. If so, specify a different project using the --startup-project option and try again.

image

问题解释:这不是很严重的问题,因此错误用黄色显示。由于当前版本的EF 命令行工具对于.NetStandard支持有限,因此会出现一个警告信息。若是真的想要修改这个问题,目前只能经过修改csproj文件,将targetFramework修改成netcoreapp1.1.

 

问题5:没法初始化DbContext

重现方法:CMD执行代码迁移

报错内容:No parameterless constructor was found on 'BlogDbContext'. Either add a parameterless constructor to 'BlogDbContext' or add an implementation of 'IDbContextFactory<BlogDbContext>' in the same assembly as 'BlogDbContext'.

问题解释:由于文中的DbContext 没有给出无参构造器,要么给出无参构造器,要么实现IDbContextFactory。此处又出现了分支,按惯例,先说简单的:经过-s|—startup-project参数让mvc程序注入一个“'IDbContextFactory<BlogDbContext>”,这样DbContext 就能够正常初始化了。

相对比较复杂的方法须要修改代码,详见问题6.

处理方法:CMD执行行命令“dotnet ef migrations add initialCreate -s ..\EfCore11.SomeUI

修复检查

image

问题6:实现无参构造器的DbContext参与迁移

重现方法:

   修改代码:DataSqlServer的BlogDbContext.cs文件

  1 using EfCore11.Domain;
  2 using Microsoft.EntityFrameworkCore;
  3 
  4 namespace EfCore11.DataSqlServer
  5 {
  6     public class BlogDbContext : DbContext
  7     {
  8         public DbSet<Post> Post { get; set; }
  9         public DbSet<Blog> Blog { get; set; }
 10 
 11         //public BlogDbContext(DbContextOptions<BlogDbContext> option)
 12         //    : base(option)
 13         //{
 14 
 15         //}
 16 
 17         // 由于使用无参构造器,因此须要自带连接字符串
 18         protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
 19         {
 20             optionsBuilder.UseSqlServer("server=(localdb)\\mssqllocaldb;database=Ef.Core;Trusted_connection=true;");
 21         }
 22     }
 23 }

   执行命令:dotnet ef migrations add initialCreate

再执行命令:dotnet ef database update

报错内容:Could not load file or assembly 'System.Data.SqlClient, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. 绯荤粺鎵句笉鍒版寚瀹氱殑鏂囦欢銆  

        :Could not load file or assembly 'System.Diagnostics.DiagnosticSource, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

问题解释:错误信息不一样是由于DbContext项目使用了不一样的targetFramework,若是是targetFramework=netstandard1.4,则错误为没法加载System.Data.SqlClient,若是按照问题4修改了targetFramework=netcoreapp1.1,则错误为没法加载 System.Diagnostics.DiagnosticSource。

这个问题确实很奇葩,从错误信息彻底不能弄清到底该怎么处理。目前ef team给出的解决办法有点儿绕,又使用了MVC项目。我相信这个解决方法只是一个临时处理措施,后期EF Team会妥善处理这个问题。

处理方法:CMD执行行命令“dotnet ef database update -s ..\EfCore11.SomeUI”     //walkaround

修复检查:执行命令时会显示建立数据库的sql语句

image

 

问题处理完毕,最终结果是

image

 

另外还想跟园子里的小伙伴们分享一个消息:

Oracle终于回应开发者们的请求了:2017年末先后开发完基于dotnet core 的ODP驱动

site

statment

详情见:Statement of Direction: ODP.NET on Microsoft .NET Core

 

做者:豆浆不放糖

博客:https://www.cnblogs.com/soldout

本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。

相关文章
相关标签/搜索