在配置好 EFCore 并生成数据库后,就可以面向实体对象进行数据读写了,之前说到 DbContext 相当于逻辑上的数据库,所以读写数据需要 new 一个前面创建的 DbContext 类,然后对 DbContext 类中的 DbSet 进行查询或者修改即可。

添加数据:

using (MyDbContext ctx = new MyDbContext())
{
    ctx.Books.Add(new Book { Title = "C++ Primer Plus", Author = "1", Price = 80, Time = DateTime.Now });
    ctx.Books.Add(new Book { Title = "Algorithms Fourth Edition", Author = "2", Price = 100, Time = DateTime.Now });
    ctx.Books.Add(new Book { Title = "Effective C++", Price = 40, Author = "3", Time = DateTime.Now });
    await ctx.SaveChangesAsync();
    
}

由于 DbContext 实现了 IDisposable 接口,所以使用 using 语句加快内存释放。注意到,对 DbSet 修改之后,仅仅只是 C# 内存中发生了变化,需要执行 SaveChange 或者 SaveChangeAsync 方法让数据库更新,这里使用了异步方法。

使用 Linq 查询:

Console.WriteLine(ctx.Books.Count());
foreach (var book in ctx.Books.Where(e => e.Author == "2"))
{
    Console.WriteLine(book.Title);
}

如果需要修改某个实体,那么需要先查询到,再对其对象进行修改,例如下面的代码将名为 Effective C++ 的实体的价格全部改为 999:

foreach (var book in ctx.Books.Where(e => e.Title == "Effective C++"))
{
    book.Price = 999;
}
await ctx.SaveChangesAsync();

从这里可以看出 EFCore 的一个不足,就是在对批量数据进行修改或者删除时,默认的效率并不高,因为 EFCore 背后会将每一次查询和修改都翻译为 SQL 语句,并交给数据库系统执行。而在这里,查询虽然是一次性的,但是每一次对价格的修改都会被转换为单独的一条 ALTER 语句,这与平时使用一行 SQL 语句不同。当然 EFCore 之后的版本肯定会增加对批量处理的支持,并且目前也有第三方的补丁来解决这个问题。