EF Core连接不同数据库
MySql
Mysql.EntityFrameworkCore:官方、不开源、下载量相对较低
Pomelo.EntityFrameworkCore.MySql(推荐):开源开发者、一直活跃
var serverVersion = new MySqlServerVersion(new Version(5, 6, 0));
optionsBuilder.UseMySql(connectionString, serverVersion)
PostgreSQL
optionsBuilder.UseNpgsql(connectionString)
SQL Server
Microsoft.EntityFrameworkCore.SqlServer
optionsBuilder.UseSqlServer(connStr);
反向工程
反向工程类似DBFirst,根据数据库来反向生成实体类,适合通过已有数据库表来生成实体类。这样一定是一个贫血模型,不要使用!
命令
//Scaffold-DbContext 连接串 数据库类型
//-force表示覆盖已有文件
Scaffold-DbContext 'Data Source=N30001084B002\SQL;AttachDbFilename=D: \My Visual Studio\MySQLServer\MyInstance\DepartmentMIS.mdf; Integrated Security=False;Connect Timeout=30; User Id =yanwenlong;Password =nrec1234.' Microsoft.EntityFrameworkCore.SqlServer -force
注意
- 生成的实体类可能不能满足项目要求,可能需要手动修改或者增加配置,比如T_Books表名生成了TBook类
- FluentAPI方式把所有的表附加配置写到DbContext派生类的OnModelCreating中,而非单独的Config类
- 若再次运行反向工程工具,对文件所做的任何更改都将丢失
实体跟踪机制
代码查看快照跟踪机制的过程
//获得实体在EF CORE中的跟踪对象EntityEntry
EntityEntry e1=ctx.Entry(a1);
//State属性代表实体的状态
e1.State
//实体的变化信息(快照值和当前值对比)
e1.DebugView.LongView
取消实体跟踪
当我们只显示,不修改数据的时候,不需要跟踪。只需要在查询时加上AsNoTracking即可,这样对象状态为Detached
注意,这样对象被修改时不会被更新到数据库
var items=ctx.Articles.AsNoTracking().Take(3)
实体的状态
- 已添加(Added):DbContext正在跟踪此实体,但数据库中尚不存在该实体
- 未改变(Unchanged):DbContext正在跟踪此实体,该实体存在于数据库中,其属性值和数据库中读取到的值一致,未发生改变
- 已修改(Modified):DbContext正在跟踪此实体,并存在于数据库中,并且其部分或全部属性值已修改
- 已删除(Deleted):DbContext正在跟踪此实体,并存在于数据库中,但是在下次调用SaveChanges时要从数据库中删除对应数据
- 已分离(Detached):DbContext未跟踪此实体,new一个对象,但是和DbContext未产生关系
SavaChanges操作对实体的影响
- 已分离、未改变的实体,会忽略
- 已添加的实体,会插入到数据库
- 已修改的实体,会更新到数据库
- 已删除的实体,会从数据库删除
状态跟踪机制的妙用
使用EF Core时,更改数据其实会执行两条SQL语句,先查询再更新
var a = ctx.Articles.Where(a => a.Id == 9).Single();//select
a.Price = 99;
ctx.SaveChanges();//update
可以采用状态跟踪,直接生成udpate、delete语句
Article a = new Article { Id = 6, Price = 99 };
var entry1=ctx.Entry(a);
entry1.Property("Price").IsModified = true;
ctx.SaveChanges();
Article a = new Article { Id = 6 };
ctx.Entry(a).State = EntityState.Deleted;
ctx.SaveChanges();
警告:
- 不推荐使用,因为会有坑。只要能看懂即可
- 当项目复杂后,代码可读性、可维护性不同,而且使用不当有可能造成不容易发现的Bug。带来的性能提升也是微乎其微的,因此不推荐使用,知道即可
EF Core对实体操作的秘密
EF Core不是通过实体对象的属性的get、set来进行属性的读写
基于性能和对充血模型支持的考虑,EF Core在读写属性的时候,如果可能,它会直接跳过get、set,而直接操作真正存储属性值的成员变量。EF Core在读写实体对象的属性时,会查找属性对应的成员变量,如果能找到,EF Core会直接读写这个成员变量的值,而不是通过set和get代码块来读写
EF Core会尝试按照命名规则去直接读写属性对应的成员变量
EF Core会尝试按照命名规则(具体的规则有很多)去直接读写属性对应的成员变量,只有无法根据命名规则找到对应成员变量的时候,EF Core才会通过属性的get、set代码块来读写属性值
应用场景:在充血模型中会用到
如何取消这种行为
可以在FluentAPI中通过UsePropertyAccessMode()方法来修改默认的这个行为,不建议修改