EF Core 的基本使用及常见的坑
1. EF Core 是什么
简单来说,就是实现代码中的类到数据库中表的映射的一种方法。
宝啊,是不是觉得我才开篇就鬼话连篇。
举个例子,假设我们要创建一个名为employees的表,包含id、name、age和salary列,应该执行如下sql语句:
CREATE TABLE employee ( id INT PRIMARY KEY, name VARCHAR(50), age INT, salary DECIMAL(10, 2)
);
这种写法很不方便,如果表很多,或者想要修改表会很不方便。
对于程序员而言,我们对于类很熟悉
public class Employee{public int Id { get; set; }public string Name { get; set; }public int Age { get; set; }public float Salary { get; set; }}
EF core就是能够将像上面的类转换成表,说的装逼一点就是将类映射到数据库表中,这样是不是比你写sql语句简单太多了。
当然,你可能会问,C# 中的int对应数据库中什么数据类型,string又对应什么类型,宝啊,你操这个心干嘛?EF Core 会自己转换的。宝啊,你可能又会问映射这种方式靠谱吗?会不会效率很低?宝啊,你觉得设计这个框架的人会比你傻吗?
2.怎么使用EF core
上面已经写好类了,是不是可以直接映射了。还不行,因为数据库怎么知道C#代码,C#代码也不认识数据库,它们两个想要建立连接,还需要通过一个桥梁DbContext。
DbContext是 DataBase Context的简写,翻译过来就是数据库上下文,这又是什么鬼?你就它当作一个名词来看待,它的作用是用来配置如何连接或者操作数据库的。DbContext官方已经写好了,我们直接继承该类使用。
class MyDbContext : DbContext{//摘要:// 把Employees { get; set; },理解成是一个容器// 用来存放Employee类型的实体,该实体名字叫做Employees// 该容器的作用是用来实现实体类到数据库表的映射// 映射的时机: Program.cs 里调用 await ctx.SaveChangesAsync();public DbSet<Employee> Employees { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){摘要:下面的连接字符串是用来连接sqlservr用的: 连接SQLserver需要nuget安装 Microsoft.EntityFrameworkCore.SqlServer 以下是代码://string connStr = "Server=.;Database=demo1;Trusted_Connection=True;Encrypt=false;";//optionsBuilder.UseSqlServer(connStr);//摘要:下面的连接字符串是用来连接mysql用的// 同时还需要指定mysql的版本号// 连接MySQL需要nuget安装 Pomelo.EntityFrameworkCore.MySql // string MySqlConneStr = "server=localhost;user=root;password=123456;database=demo1";//特别注意:此处使用的是:Pomelo.EntityFramework.MySql包.var serverVersion = new MySqlServerVersion(new Version(8, 0, 34));optionsBuilder.UseMySql(MySqlConneStr, serverVersion);}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);}}
现在是2024.02.01 0:14,好困啊,我先睡觉
现在时间2024.02.01 16:43,咱接着写。
将类映射到数据库这个过程我们叫做数据库迁移
实体类Employee和数据库上下文类MyDbContext都写好了,是不是可以执行数据迁移了,宝,还不行,如果你是直接拷贝我的代码,有没有发现出现一些错误,这是因为我们没有添加对相关包的引用。
图中区域1是我们需要的依赖包。通过install-package 包名字 在控制台安装,有时候我会偷懒双击项目名字(区域2),我们安装的包将会出现区域3,我们可以直接将以下的ItemGroup替换文件中的,系统会自己安装依赖包,很方便。
<ItemGroup><PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" /><PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" /><PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0"><PrivateAssets>all</PrivateAssets><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets></PackageReference><PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0-beta.2" />
</ItemGroup>
接下来我们就可以做数据库迁移了:
- 控制台执行:add-migration name;
- 再执行:update-database
执行成功后,就可以去数据库中看到自己创建的表了。
怎么给数据库中字段设置属性,或者给表自定义一个名字,可以通过以下的方式
public class BookEntityConfig : IEntityTypeConfiguration<Employee>
{public void Configure(EntityTypeBuilder<Employee> builder){builder.ToTable("T_Employee"); //ToTable这个扩展方法来自Microsoft.EntityFrameworkCore.Toolsbuilder.Property(x=> x.Name).IsRequired().HasMaxLength(20); //配置是否为空和最大长度}
}
则呢么和数据库交互呢?我们以插入数据为例,执行下面的代码数据库里面就插入一条数据了。
using MyDbContext ctx = new MyDbContext();
Employee employee = new Employee { Age = 18, Name = "张三",Salary=5000 };
ctx.Add(employee);
ctx.SaveChanges();
还可以通过依赖注入的方式来连接数据库,如果宝不知道怎么弄,评论区可以告诉我,我抽空把这个点加上。
3. EF Core使用过程中遇到的坑
我写这篇博客的主要目的不是告诉你怎么使用EF Core,那个网上的教程很多,我主要想说说我使用EF Core遇到的坑
,有的坑真的把我搞吐了,我要把它记录下来。
3.1 数据库迁移没有选择指定项目
下图我们是针对“写博客用的测试”这个项目进行数据库迁移,但我在控制台中选择的默认项目“EFCore最简单的应用”这个项目,这样肯定会迁移失败
3.2 没有引用mysq第三方安装包
如果你使用Mysql就要引用 “Pomelo.EntityFrameworkCore.MySql” 这个包,这里面还有坑,因为我是用的是 "Microsoft.EntityFrameworkCore“版本是8.0,所以我引用的mysql的包要是 ,版本要匹配。
3.3 执行数据库迁移时报错
前面的问题,代码中可能就有错误提示,比如你少了包啥的,但是数据库迁移这里才报错,有时候就挠头了,特别是对新手。数据库迁移时,需要用到另外一个包Microsoft.EntityFrameworkCore.Tools,没装这个包是做不了数据哭迁移的,很多时候是因为这个原因,也可以再项目中添加一个类。
public class DbContextDesignTimeFactory : IDesignTimeDbContextFactory<MyDbContext>
{public MyDbContext CreateDbContext(string[] args){DbContextOptionsBuilder<MyDbContext> bulider = newDbContextOptionsBuilder<MyDbContext>();string MySqlConneStr = "server=localhost;user=root;password=123456;database=demo1";//特别注意:此处使用的是:Pomelo.EntityFramework.MySql包.var serverVersion = new MySqlServerVersion(new Version(8, 0, 35));bulider.UseMySql(MySqlConneStr, serverVersion);return new MyDbContext(bulider.Options);}
}
3.4 之前都已经迁移成功了,现在又突然用不了
宝啊,你肯定会遇到,数据库已经迁移成功了,之前还能用,现在又用不了,出现这个原因多半是你改了表结构,比如你修改了表名,或者某个字段的属性,这时候,你可以把数据库中的表删除,然后再执行一次数据迁移试试。
3.5 同一个工程文件下其他项目错误
同一个解决方案下其他项目错误导致本项目数据迁移失败,我前几天就遇到这个问题。假如以下3个文件都需要使用数据迁移,我正确配置了“写博客用的测试”这个项目,但没有正确配置“EFCore最简单的应用”,那也会导致数据迁移失败。
当实在找不到原因时,要来这了看一下信息,有时候会有意想不到的收获