0.前言

到目前为止,我们看了一下如何声明EF Core的初步使用,也整体的看了下EF Core的映射关系配置以及导航属性的配置。

这一篇,我带大家分享一下,我在工作中需要的EF Core的用法。

1. 初始化

在实际开发中,一般都是先设计好数据表再进行开发,所以很少用到EF Core的数据迁移功能。所以EF Core的初始化,一般也指的是EF Core上下文初始化。

1.1 连接字符串

我们通过前面的文章知道,EF Core在上下文初始化的时候,都需要一个链接字符串。如果在不考虑后续变更或者上下文的复用性,可以直接在自定义Context里重写OnConfiguring方法中定义。

如果需要后续变更,那么就需要在创建自定义EF Core 上下文类的时候,为之添加一个连接字符串的属性或者字段,以方便初始化的时候指定。实例:

public class DefaultContext : DbContext
{
private string Connection { get; set; } = "Data Source=./blogging1.db";
public DefaultContext(string connection)
{
Connection = connection;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite(Connection);
}

这样一来,我们在后续使用的时候,就可以指定连接字符串了。当然了,如果有小伙伴有更好的方法也可以分享出来呀。

1.2 配置文件的加载或者实体对象的托管

如果我们不使用配置文件的话,就必须在EF Core的上下文类里添加一个类型是DbSet<T>的属性。继续延续上面的实例:

public class SingleModel
{
public int Id { get; set; }
public int TargetId { get; set; }
public SingleTargetModel SingleTarget { get; set; }
} public class SingleTargetModel
{
public int Id { get; set; }
public SingleModel Single { get; set; }
}
public class DefaultContext : DbContext
{
// 其余代码参见 1.1 DefaultContext
public DbSet<SingleModel> Singles { get; set; }
public DbSet<SingleTargetModel> Targets { get; set; }
}

以上也就是这一小节标题中的实体对象的托管。我没找到EF Core官方文档中对于这种方式的称呼,所以我就悄悄的抢注了一下为托管。

如果我们使用Config类(也就是 《C# 数据操作系列 - 7. EF Core 导航属性配置》中介绍的配置类)的话,需要在EF Core中应用配置,具体是:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new SingleModelConfig());
modelBuilder.ApplyConfiguration(new SingleTargeModelConfig());
}

在使用的时候,可以直接:

var context = new DefaultContext("Data Source=demo.db");
var t1 = context.Set<SingleTargetModel>().First();

即使用DbContext.Set<T>,可以获取到一个数据加载集,当然也可以结合实体类的托管来一起使用。

那么为什么,我推荐使用配置类加载吗?

因为在实际开发中,一个完整的程序或者网站实体类都会大于10,而这些如果使用属性的形式会非常多,不利于实际开发。而且,EF Core可以通过 Assembly 方式整体加载配置文件。再者,为了保证ORM中的O不受其他因素的影响。也就是说,如果使用注解形式配置映射关系,那么势必会造成影响。

当然了,使用配置文件必然会导致项目的类增多,而且大量的重复类可能会出现。当然了,如果考虑到这个问题的话,可以试试写一个项目代码生成器哦,专门用来处理这些差不多的类。

咳咳,总而言之,使用配置文件利大于弊,所以我推荐使用配置文件对关系进行配置。

2. 数据变化

换句话说,嗯,也就是增删改。在数据增删这两方面,EF Core没有太多需要注意的地方。不过如果有导航属性的话,在新增的时候,EF Core会自动检索导航属性的另一端是否需要新增到数据库中,如果需要新增的话,EF Core会自动标记为新增的。

而删除,如果在配置导航属性时,没有设置级联删除,删除当前元素,如果另一端的外键是可空类型的,并不会删除导航属性另一端的元素只会设置外键指向为NULL,如果另一端外键是不可空的,那么就会同时删除。如果需要修改,可以使用以下方法修改,在配置导航属性的时候:

OnDelete(DeleteBehavior.Cascade);

对于可为NULL的外键来说,枚举DeleteBehavior的值起以下作用:

行为名称 对内存中的依赖项/子项的影响 对数据库中的依赖项/子项的影响
Cascade 删除实体 删除实体
ClientSetNull(默认) 外键属性设置为 null None
SetNull 外键属性设置为 null 外键属性设置为 null
Restrict None None

而对于不可为NULL的外键来说,枚举DeleteBehavior的值起以下作用:

行为名称 对内存中的依赖项/子项的影响 对数据库中的依赖项/子项的影响
Cascade(默认) 删除实体 删除实体
ClientSetNull SaveChanges 引发异常 None
SetNull 引发 SaveChanges SaveChanges 引发异常
Restrict None None

而对于数据的修改,EF Core的做法是通过监控实体的ChangeTracker来实现对数据实体的状态更新。也就是说,如果你从EF Core的上下文获取了一个实体对象,对这个对象的某些值进行了修改。这时候EF Core其实已经记录了这个对象的修改。不需要我们额外的调用修改方法(因为根本没有Update方法)。

EF Core在我们调用 SaveChanges 会把缓存的所有更改(增、删、改)都推送给数据库。如果有一条数据变更因为数据库校验或者其他约束没有通过,就会报错,同时撤销所有已推送的变更并取消后续变更的推送。

从数据库的角度来看,EF Core在SaveChanges的过程中是以事务的形式推送给数据库的。如果出错,那么事务就会回滚。

所以一般情况下,EF不需要开启事务。

3.花样查询

EF Core 支持Linq查询,所以在查询的时候可以使用Linq进行。简单示例如下:

var context = new DefaultContext("Data Source=demo.db");
var results = from t in context.Set<SingleTargetModel>()
select t;

当然,也可以使用方法链的形式传入一个Expression<Func<T,bool>> 类型的表达式。

var results = context.Set<SingleTargetModel>().Where(t=>true);

看到这里了,可能会有疑问了,这明明很简单呀。是的,如果只是查询,自然简单。

那么,结合排序、分页之后呢?先来看看排序是怎么实现的吧。

在查询表达式写法中,排序应该这样的写的:

var results = from t in context.Set<SingleTargetModel>()
orderby t.Id //descending 如果降序则取消注释
select t ;

方法链的形式是:

var results = context.Set<SingleTargetModel>().Where(t=>true).OrderBy(t=>t.Id);

分页只能通过方法链的形式进行分页,这里提供一个分页的工具方法:

public static IQueryable<T> Paging<T>(IQueryable<T> source,int pageIndex,int pageSize)
{
return source.Skip(pageSize * (pageIndex - 1)).Take(pageSize);
}

这里用到的是 Skip(int count) 表示忽略数据集的前count条记录,Take(int count)取得数据集的前count条记录。

EF Core在调用 ToList的时候,会将已调用的方法和Linq转换成SQL语句,并正式向数据库发起查询。如果出现了在Linq中调用三方方法或者自己写的工具方法的话,可能会提示不受支持。

如果使用的Linq表达式,则没关系,EF Core在遇到这种情况的时候,会把数据库里所有数据都加载到上下文中,再执行后续的查询等操作。

所以,为了高效的查询,在执行查询的时候,最好使用简单的查询条件。

4. 后续

EF Core整体使用已经介绍完了,当然照例是普通工程级的内容。下一篇我给大家介绍一下EF Core剩下一些边角料,嗯。如果要深挖代码的话,得以后有机会了。

数据访问系列,EF Core 篇即将到一段落。待EF Core篇完成后,将带领一起去探索 Nhibernate和Dapper,SqlSugar这三个ORM框架。

更多内容烦请关注我的博客《高先生小屋》

C# 数据操作系列 - 8. EF Core的增删改查的更多相关文章

  1. C# 数据操作系列 - 6 EF Core 配置映射关系

    0. 前言 在<C# 数据操作系列 - 5. EF Core 入门>篇中,我们简单的通过两个类演示了一下EF增删改查等功能.细心的小伙伴可能看了生成的DDL SQL 语句,在里面发现了些端 ...

  2. C# 数据操作系列 - 9. EF Core 完结篇

    0.前言 <EF Core>实际上已经可以告一段落了,但是感觉还有一点点意犹未尽.所以决定分享一下,个人在实际开发中使用EF Core的一些经验和使用的扩展包. 1. EF Core的异步 ...

  3. C# 数据操作系列 - 5. EF Core 入门

    0.前言 上一章简单介绍了一下ORM框架,并手写了一个类似ORM的工具类.这一章将介绍一个在C#世界里大名鼎鼎的ORM框架--Entity Framework的Core版. Entity Framew ...

  4. C# 数据操作系列 - 7. EF Core 导航属性配置

    在上一篇,大概介绍了Entity Framework Core关于关系映射的逻辑.在上一篇中留下了EF的外键映射没有说,也就是一对一,一对多,多对一,多对多的关系等.这一篇将为大家细细分析一下,如何设 ...

  5. Entity - 使用EF框架进行增删改查 - 模型先行

    模型先行:先创建数据库实体模型,然后再进行数据库的增删改查. 基本步骤是不变的,可参照 <Entity - 使用EF框架进行增删改查 - 数据库先行> 其中的不同是,在创建数据库实体模型的 ...

  6. ASP.NET CORE系列【二】使用Entity Framework Core进行增删改查

    介绍 EntityFrameworkCore EF core 是一个轻量级的,可扩展的EF的跨平台版本.对于EF而言 EF core 包含许多提升和新特性,同时 EF core 是一个全新的代码库,并 ...

  7. ASP.NET CORE系列【三】使用Entity Framework Core进行增删改查

    身份验证 以前我们熟悉的web.config中配置的form验证,现在没有了.我们来看看在Core里面如何配置: 首先需要NuGet安装一个包:Microsoft.AspNetCore.Authent ...

  8. MySQL数据库学习笔记(九)----JDBC的ResultSet接口(查询操作)、PreparedStatement接口重构增删改查(含SQL注入的解释)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  9. 我来讲讲在c#中怎么进行xml文件操作吧,主要是讲解增删改查!

    我把我写的四种方法代码贴上来吧,照着写没啥问题. 注: <bookstore> <book> <Id>1</Id> <tate>2010-1 ...

随机推荐

  1. Java多台中成员访问特点

    多态中的成员访问特点: A:成员变量 编译看左边,运行看左边 B:构造方法 创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化 C:成员方法 编译看左边,运行看右边.//因为调用对象时,子 ...

  2. 即时通信WebSocket 和Socket.IO

    WebSocket HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯. 在2008年诞生,2011年成为国际标准. 现在基本所有浏览器都已经支持了. We ...

  3. Codeforces 1340B Nastya and Scoreboard(dp,贪心)

    题目链接OvO 题目大意   给你\(n\)串数字,\(1\)代表该位置是亮的,\(0\)代表是灭的.你必须修改\(k\)个数字,使某些\(0\)变为\(1\).注意,只能把原来的\(0\)改成\(1 ...

  4. shell脚本:备份数据库、代码上线

    备份MySQL数据库场景:一台MySQL服务器,跑着5个数据库,在没有做主从的情况下,需要对这5个库进行备份 需求:1)每天备份一次,需要备份所有的库2)把备份数据存放到/data/backup/下3 ...

  5. Python玩转人工智能最火框架 TensorFlow应用实践 学习 教程

    随着 TensorFlow 在研究及产品中的应用日益广泛,很多开发者及研究者都希望能深入学习这一深度学习框架.而在昨天机器之心发起的框架投票中,2144 位参与者中有 1441 位都在使用 Tenso ...

  6. QT 无法抓住异常

    出处:https://stackoverflow.com/questions/40980171/qt5core-dll-crashing I've found that enabling /EHa ( ...

  7. Spring Cloud 系列之 Stream 消息驱动(一)

    在实际开发过程中,服务与服务之间通信经常会使用到消息中间件,消息中间件解决了应用解耦.异步处理.流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构. 不同中间件内部实现方式是不一样的,这些中间 ...

  8. 数据库SQL---数据库、基本表、视图、索引的定义、修改、删除

    1.SQL(结构化查询语言)的组成:数据定义语言DDL.数据操纵语言DML.数据控制语言DCL.其他. 2.SQL语言的功能: 1)数据查询:SELECT 2)数据定义:CREATE   DROP  ...

  9. AndroidStudio提高编译速度的建议

    1.使用最新的Android gradle插件 Google tools team一直致力于提高android studio的编译速度,使用最新的gradle插件可以搞编译速度 在Android Gr ...

  10. 6.Python中内存是如何管理的?

    Python中内存是如何管理的? Python memory is managed by Python private heap space. All Python objects and data ...