EntityFrameworkCore3.x 的初步了解与使用,简单错误的处理
我是一个开发的初学者,之前也会编程,但只会写写Hello World和一些简单的数据结构与算法,从来没能够用代码真正做出什么东西。但是现在面临着毕业,今年这个形势,又不能混着混着就找到工作,所以我准备学习Asp.Net Core,现在的稳定版本是3.1,还有一个.NET5预发行版,我先学3.1。
我了解到做web应用的后端,增删改查是核心功能,而Asp.Net Core做后端的话,EntityFramework Core是一个官方的ORM(对象关系映射),我打算先学习这种官方提供的工具,等我真正能做出东西来,又有余力的时候,再去接触第三方的ORM。
我看过一点点视频教程和博客,发现大佬们在做教学的时候,侧重点都在EFCore的使用,而忽略了配置。大部分人都是用的Sqlite或者localdb,几乎没有见到真正用SqlServer来示范的。数据库连接字符串也是常常写到DbContext的OnConfiguring方法里或者Startup里,而不是放到appsettings.json这个配置文件里。对于我这种连数据库连接字符串都没写过的纯种的萌新,完全无法举一反三,不知道该怎样使用真正的SqlServer来配合EntityFramework Core,官方文档也是这一嘴那一嘴,看起来不太方便。
今天总结一下简单的使用方法以及我碰到的坑。
首先我创建了一个简单的Web Api项目,然后添加两个.net core类库,现在整个解决方案就包含一个web api项目和两个.net core类库:
Api项目主要是Controller,Core项目是用来放实体和Dto模型等,Infrastructure打算用来放DbContext以及将来的Repositories。
添加一下引用关系,Api依赖Core和Infrastructure,Infrastructure依赖Core。
右键每个类库的依赖项,点添加引用,把要添加的引用勾选上就行了。
首先我在Core下创建一个Entities文件夹,用来存放实体模型,然后在它下面创建一个Post实体模型:
然后我在Infrastructure下用Nuget包管理器先安装EntityFramework Core:
安装了上面三个包(听说安装SqlServer这个包就自动包括了EFCore这个包,我没有尝试),然后我在Infrastructure下创建一个Data文件夹,在里面创建一个ClamContext,继承DbContext:
注意构造函数的写法。因为我们想要创建一个Posts数据表,映射到我们的实体模型Post,所以用DbSet<Post>。注释掉的是一种进阶的用法,也是我踩过的坑,先不用。
然后我去Api下的appsettings.json里添加数据库连接字符串:
连接字符串我不会写,也是瞎抄的。Server的值要改成自己本机安装的数据库server名,另外我想创建一个叫Clam的数据库,就把Database的值改成Clam。使用windows身份验证。如果项目要部署到linux的服务器上的话,可能要进行修改。如果部署后代码要放到Github上开源的话,可能数据库连接字符串也不能放到appsettings.json这个配置文件里,否则就暴露自己的数据库的Server地址了,这些都到时候再说,现在先不管。
注意,现在我并没有在我本机的SqlServer里创建这个数据库,我们使用EFCore来帮我们创建。
然后我们去Api下的Startup.cs类中进行配置:
这样就配置好了,然后我们要在Api下安装EntityFrameworkCore.Design这个包,不然会报错。
然后就可以迁移和更新数据库了。打开程序包管理器控制台:
首先,在控制台中把默认项目选择成Infrastructure:
然后再下面的控制台里用Add-Migration InitialCreation指令来添加迁移,后面的InitialCreation是我给迁移起的名字,可以随便起,但最好能看出是初始化的迁移,名字要有意义。然后再用Update-Database来更新数据库。
如果数据库迁移弄错了,千万不要直接删掉迁移文件,最好使用Remove-Migration来删除上一条迁移。
迁移完之后,Infrastructure里会生成一个迁移文件夹:
上面日期开头的是迁移文件,点进去就能看到用来创建数据库、表之类的一些代码,读起来跟读英语一样,容易理解。
下面这个模型快照我也不知道是Update以后生成的还是迁移以后就有的,我忘了看了,迁移的时候没有bug导致我太兴奋,一口气Update了。
打开SqlServer SSMS看一下:
我们没有在SqlServer里手动创建数据库,Clam这个数据库就已经自动创建好了,Posts表也建好了,三列就是我们Post实体模型里的三个属性。ORM是对象关系映射,意思可能就是把数据库的表映射到一个我们的对象上,每一个表就是一个实体模型的对象,表的每一列就是这个对象的每一个属性。
下面总结一下错误以及解决办法:
出现了问题先检查一下你的EFCore的包安装的是不是稳定版本,不要装5.x的Preview版本。
如果添加迁移的时候出现以下错误:
No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext
它似乎让我们重写一下OnConfiguring,也就是我注释掉的那部分,我们先不管,那是一些进阶的或者高级的操作,这个方法也是来配置的。但我们已经直接在Startup里依赖注入进行配置了。
所以我猜测是你的默认启动项目不是Api而是Infrastructure,导致Api里进行依赖注入的配置,也就是Startup里进行的配置没能用上,所以要把Api设定成默认启动项目。
应该把启动项目设置成Api这个项目:
如果Api是启动项目,依然出现这个问题,可能就是Startup里没写对。还有可能是DbContext里的构造函数那里出了问题,仔细检查一下。
如果出现了这个问题:
Your startup project 'ClamHub.Api' doesn't reference Microsoft.EntityFrameworkCore.Design. This package is required for the Entity Framework Core Tools to work. Ensure your startup project is correct, install the package, and try again.
就很显然了,去给Api装上Design这个包就行了。
其他的问题等我遇到了再记录。