Entity Framework Core 2.0 入门

该文章比较基础, 不多说废话了, 直接切入正题.

该文分以下几点:

  • 创建Model和数据库
  • 使用Model与数据库交互
  • 查询和保存关联数据

EF Core支持情况

Entity Framework Core 2.0 入门

EF Core的数据库Providers:

Entity Framework Core 2.0 入门

此外还即将支持CosmosDB和 Oracle.

EFCore 2.0新的东西:

查询:

  • EF.Functions.Like()
  • Linq解释器的改进
  • 全局过滤(按类型)
  • 编译查询(Explicitly compiled query)
  • GroupJoin的SQL优化.

映射:

  • Type Configuration 配置
  • Owned Entities (替代EF6的复杂类型)
  • Scalar UDF映射
  • 分表

性能和其他

  • DbContext Pooling, 这个很好
  • Raw SQL插入字符串.
  • Logging
  • 更容易定制配置

1.创建数据库和Model

准备.net core项目

项目结构如图:

Entity Framework Core 2.0 入门

由于我使用的是VSCode, 所以需要使用命令行:

mkdir LearnEf && cd LearnEf
dotnet new sln // 创建解决方案 mkdir LearnEf.Domains && cd LearnEf.Domains
dotnet new classlib // 创建LearnEf.Domains项目 cd ..
mkdir LearnEf.Data && cd LearnEf.Data
dotnet new classlib // 创建LearnEf.Data项目 cd ..
mkdir LearnEf.UI && cd LearnEf.UI
dotnet new console // 创建控制台项目 cd ..
mkdir LearnEf.Tests && cd LearnEf.Tests
dotnet new xunit // 创建测试项目

为解决方案添加项目:

dotnet sln add LearnEf.UI/LearnEf.UI.csproj
dotnet sln add LearnEf.Domains/LearnEf.Domains.csproj
dotnet sln add LearnEf.Data/LearnEf.Data.csproj
dotnet sln add LearnEf.Tests/LearnEf.Tests.csproj

为项目之间添加引用:

LearnEf.Data依赖LearnEf.Domains:

cd LearnEf.Data
dotnet add reference ../LearnEf.Domains/LearnEf.Domains.csproj

LearnEf.Console依赖LearnEf.Domains和LearnEf.Data:

cd ../LearnEf.UI
dotnet add reference ../LearnEf.Domains/LearnEf.Domains.csproj ../LearnEf.Data/LearnEf.Data.csproj

LearnEf.Test依赖其它三个项目:

cd ../LearnEf.Tests
dotnet add reference ../LearnEf.Domains/LearnEf.Domains.csproj ../LearnEf.Data/LearnEf.Data.csproj ../LearnEf.UI/LearnEf.UI.csproj

(可能需要执行dotnet restore)

在Domains项目下直接建立两个Model, 典型的一对多关系Company和Department:

using System;
using System.Collections.Generic; namespace LearnEf.Domains
{
public class Company
{
public Company()
{
Departments = new List<Department>();
} public int Id { get; set; }
public string Name { get; set; }
public DateTime StartDate { get; set; }
public List<Department> Departments { get; set; }
}
}
namespace LearnEf.Domains
{
public class Department
{
public int Id { get; set; }
public int CompanyId { get; set; }
public Company Company { get; set; }
}
}

添加Entity Framework Core库:

首先Data项目肯定需要安装这个库, 而我要使用sql server, 参照官方文档, 直接在解决方案下执行这个命令:

dotnet add ./LearnEf.Data package Microsoft.EntityFrameworkCore.SqlServer
dotnet restore

创建DbContext:

在Data项目下创建MyContext.cs:

using LearnEf.Domains;
using Microsoft.EntityFrameworkCore; namespace LearnEf.Data
{
public class MyContext : DbContext
{
public DbSet<Company> Companies { get; set; }
public DbSet<Department> Departments { get; set; }
}
}

指定数据库Provider和Connection String:

在EFCore里, 必须明确指定Data Provider和Connection String.

可以在Context里面override这个Onconfiguring方法:

Entity Framework Core 2.0 入门

有一个错误, 应该是Server=localhost;

(这里无需调用父类的方法, 因为父类的方法什么也没做).

UseSqlServer表示使用Sql Server作为Data Provider. 其参数就是Connection String.

在运行时EfCore第一次实例化MyContext的时候, 就会触发这个OnConfiguring方法. 此外, Efcore的迁移Api也可以获得该方法内的信息.

EF Core迁移:

简单的来说就是 Model变化 --> 创建migration文件 --> 应用Migration到数据库或生成执行脚本.

添加Migration (迁移):

由于我使用的是VSCode+dotnet cli的方法, 所以需要额外的步骤来使dotnet ef命令可用.

可以先试一下现在的效果:

Entity Framework Core 2.0 入门

可以看到, dotnet ef 命令还不可用.

所以参考官方文档: https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet

可执行项目(Startup project)需要EFCore迁移引擎库, 所以对LearnEf.UI添加这个库:

dotnet add ./LearnEf.UI package Microsoft.EntityFrameworkCore.Design
dotnet restore

然后打开LearnEf.UI.csproj 添加这段代码, 这个库是EF的命令库:

 <ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
</ItemGroup>

最后内容如下:

Entity Framework Core 2.0 入门

然后再执行dotnet ef命令, 就应该可用了:

Entity Framework Core 2.0 入门

现在, 添加第一个迁移:

cd LearnEf.UI
dotnet ef migrations add Initial --project=../LearnEf.Data

--project参数是表示需要使用的项目是哪个.

命令执行后, 可以看到Data项目生成了Migrations目录和一套迁移文件和一个快照文件:

Entity Framework Core 2.0 入门

检查这个Migration.

Entity Framework Core 2.0 入门

前边带时间戳的那两个文件是迁移文件.

另一个是快照文件, EFCore Migrations用它来跟踪所有Models的当前状态. 这个文件非常重要, 因为下次你添加迁移的时候, EFcore将会读取这个快照并将它和Model的最新版本做比较, 就这样它就知道哪些地方需要有变化.

这个快照文件解决了老版本Entity Framework的一个顽固的团队问题.

使用迁移文件创建脚本或直接生成数据库.

生成创建数据库的SQL脚本:

dotnet ef migrations script --project=../LearnEf.Data/LearnEf.Data.csproj

Entity Framework Core 2.0 入门

Sql脚本直接打印在了Command Prompt里面. 也可以通过指定--output参数来输出到具体的文件.

这里, 常规的做法是, 针对开发时的数据库, 可以通过命令直接创建和更新数据库. 而针对生产环境, 最好是生成sql脚本, 然后由相关人员去执行这个脚本来完成数据库的创建或者更新.

直接创建数据库:

dotnet ef database update --project=../LearnEf.Data/LearnEf.Data.csproj --verbose

--verbose表示显示执行的详细过程, 其结果差不多这样:

Entity Framework Core 2.0 入门

这里的执行过程和逻辑是这样的: 如果数据库不存在, 那么efcore会在指定的连接字符串的地方建立该数据库, 并应用当前的迁移. 如果是生成的sql脚本的话, 那么这些动作必须由您自己来完成.

然后查看一下生成的表.

不过首先, 如果您也和我一样, 没有装Sql server management studio或者 Visual Studio的话, 请您先安装VSCode的mssql这个扩展:

Entity Framework Core 2.0 入门

重启后, 建立一个Sql文件夹, 然后建立一个Tables.sql文件, 打开命令面板(windows: Shift+Ctrl+P, mac: Cmd+Shift+P), 选择MS SQL: Connect.

Entity Framework Core 2.0 入门

然后选择Create Connection Profile:

Entity Framework Core 2.0 入门

输入Sql的服务器地址:

Entity Framework Core 2.0 入门

再输入数据库名字:

Entity Framework Core 2.0 入门

选择Sql Login(我使用的是Docker, 如果windows的话, 可能使用Integrated也可以):

Entity Framework Core 2.0 入门

输入用户名:

Entity Framework Core 2.0 入门

密码:

Entity Framework Core 2.0 入门

选择是否保存密码:

Entity Framework Core 2.0 入门

最后输入档案的名字:

Entity Framework Core 2.0 入门

随后VSCode将尝试连接该数据库, 成功后右下角会这样显示 (我这里输入有一个错误, 数据库名字应该是LearnEF):

Entity Framework Core 2.0 入门

随后在该文件中输入下面这个sql语句来查询所有的Table:

--  Table 列表
SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE';

执行sql的快捷键是windows: Shift+Ctrp+E, mac: Cmd+Shift+E, 或者鼠标右键.

结果如图:

Entity Framework Core 2.0 入门

OK表是创建成功了(还有一个迁移历史表, 这个您应该知道).

接下来我看看表的定义:

-- Companies表:
exec sp_help 'Companies';

Entity Framework Core 2.0 入门

其中Name字段是可空的并且长度是-1也就是nvarchar(Max).

Departments表的Name字段也是一样的.

再看看那个MigrationHistory表:

-- MigrationHistory:
SELECT * FROM dbo.__EFMigrationsHistory;

Entity Framework Core 2.0 入门

可以看到, efcore到migration 历史表里面只保存了MigrationId.

在老版本到ef里, migration历史表里面还保存着当时到迁移的快照, 创建迁移的时候还需要与数据库打交道. 这就是我上面提到的如果团队使用ef和源码管理的话, 就会遇到这个非常令人头疼的问题.

如果使用asp.net core的话.

在解决方案里再建立一个asp.net core mvc项目:

mkdir LearnEf.Web && cd LearnEf.Web
dotnet new mvc

在解决方案里添加该项目:

dotnet sln add ./LearnEf.Web/LearnEf.Web.csproj

为该项目添加必要的引用:

cd LearnEf.Web
dotnet add reference ../LearnEf.Domains/LearnEf.Domains.csproj ../LearnEf.Data/LearnEf.Data.csproj

为测试项目添加该项目引用:

cd ../*Tests
dotnet add reference ../LearnEf.Web/LearnEf.Web.csproj

操作完之后, 我们可以做以下调整, 去掉MyContext里面的OnConfiguring方法, 因为asp.net core有内置的依赖注入机制, 我可以把已经构建好的DbContextOptions直接注入到构造函数里:

这样的话, 我们可以让asp.net core来决定到底使用哪个Data Provider和Connection String:

Entity Framework Core 2.0 入门

这也就意味着, Web项目需要引用EfCore和Sql Provider等, 但是不需要, 因为asp.net core 2.0这个项目模版引用了AspNetCore.All这个megapack, 里面都有这些东西了.

Entity Framework Core 2.0 入门

虽然这个包什么都有, 也就是说很大, 但是如果您使用Visual Studio Tooling去部署的话, 那么它只会部署那些项目真正用到的包, 并不是所有的包.

接下来, 在Web项目的Startup添加EfCore相关的配置:

 public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<MyContext>
(options => options.UseSqlServer("Server=localhost; Database=LearnEf; User Id=sa; Password=Bx@steel1;"
));
}

这句话就是把MyContext注册到了asp.net core的服务容器中, 可以供注入, 同时在这里指定了Data Provider和Connection String.

与其把Connection String写死在这里, 不如使用appSettings.json文件:

Entity Framework Core 2.0 入门

然后使用内置的方法读取该Connection String:

 public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<MyContext>
(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}

回到命令行进入Web项目, 使用dotnet ef命令:

Entity Framework Core 2.0 入门

说明需要添加上面提到的库, 这里就不重复了.

然后, 手动添加一个Migration叫做InitialAspNetCore:

dotnet ef migrations add InitialAspNetCore --project=../LearnEf.Data

看一下迁移文件:

Entity Framework Core 2.0 入门

是空的, 因为我之前已经使用UI那个项目进行过迁移更新了. 所以我要把这个迁移删掉:

dotnet ef migrations remove --project=../LearnEf.Data

然后这两个迁移文件就删掉了:

Entity Framework Core 2.0 入门

多对多关系和一对一关系:

这部分的官方文档在这: https://docs.microsoft.com/en-us/ef/core/modeling/relationships

对于多对多关系, efcore需要使用一个中间表, 我想基本ef使用者都知道这个了, 我就直接贴代码吧.

建立一个City.cs:

namespace LearnEf.Domains
{
public class City
{
public int Id { get; set; }
public string Name { get; set; }
}
}

Company和City是多对多的关系, 所以需要建立一个中间表,叫做 CompanyCity:

namespace LearnEf.Domains
{
public class CompanyCity
{
public int CompanyId { get; set; }
public int CityId { get; set; }
public Company Company { get; set; }
public City City { get; set; }
}
}

修改Company:

Entity Framework Core 2.0 入门

修改City:

Entity Framework Core 2.0 入门

尽管Efcore可以推断出来这个多对多关系, 但是我还是使用一下FluentApi来自定义配置一下这个表的主键:

MyContext.cs:

using LearnEf.Domains;
using Microsoft.EntityFrameworkCore; namespace LearnEf.Data
{
public class MyContext : DbContext
{
public MyContext(DbContextOptions<MyContext> options)
: base(options)
{ }
public DbSet<Company> Companies { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<CompanyCity> CompanyCities { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<CompanyCity>()
.HasKey(c => new
{ c.CompanyId, c.CityId });
} // protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
// {
// optionsBuilder.UseSqlServer("Server=localhost; Database=LearnEf; User Id=sa; Password=Bx@steel1;");
// base.OnConfiguring(optionsBuilder);
// }
}
}

完整的写法应该是:

Entity Framework Core 2.0 入门

其中红框里面的部分不写也行.

接下来建立一个一对一关系, 创建Model叫Owner.cs:

namespace LearnEf.Domains
{
public class Owner
{
public int Id { get; set;}
public int CompanyId { get; set; }
public string Name { get; set; }
public Company Company { get; set; }
}
}

修改Company:

Entity Framework Core 2.0 入门

配置关系:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<CompanyCity>()
.HasKey(c => new { c.CompanyId, c.CityId }); modelBuilder.Entity<CompanyCity>().HasOne(x => x.Company)
.WithMany(x => x.CompanyCities).HasForeignKey(x => x.CompanyId); modelBuilder.Entity<CompanyCity>().HasOne(x => x.City)
.WithMany(x => x.CompanyCities).HasForeignKey(x => x.CityId); modelBuilder.Entity<Owner>().HasOne(x => x.Company).WithOne(x => x.Owner)
.HasForeignKey<Owner>(x =>
x.CompanyId);
}

这里面呢, 这个Owner对于Company 来说 是可空的. 而对于Owner来说, Company是必须的. 如果针对Owner想让Company是可空的, 那么CompanyId的类型就应该设置成int?.

再添加一个迁移:

dotnet ef migrations add AddRelationships --project=../LearnEf.Data

查看迁移文件:

Entity Framework Core 2.0 入门

查看一下快照;

Entity Framework Core 2.0 入门

没问题, 那么更新数据库:

dotnet ef database update AddRelationships --project=../LearnEf.Data --verbose

更新成功:

Entity Framework Core 2.0 入门

对现有数据库的反向工程.

这部分请查看官方文档吧, 很简单, 我实验了几次, 但是目前还没有这个需求.

使用Model与数据库交互

输出Sql语句.

对于asp.net core 2.0项目, 参考官方文档: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?tabs=aspnetcore2x

实际上, 项目已经配置好Logging部分了, 默认是打印到控制台和Debug窗口的. 源码: https://github.com/aspnet/MetaPackages/blob/dev/src/Microsoft.AspNetCore/WebHost.cs

而对于console项目, 文档在这: https://docs.microsoft.com/en-us/ef/core/miscellaneous/logging

需要对LearnEf.Data项目添加这个包:

cd LearnEf.Data
dotnet add package Microsoft.Extensions.Logging.Console
dotnet restore

然后为了使用console项目, 需要把MyContext改回来:

Entity Framework Core 2.0 入门

这部分首先是使用LoggerFactory创建了一个特殊的Console Logger. .net core的logging可以显示很多的信息, 这里我放置了两个过滤: 第一个表示只显示Sql命令, 第二个表示细节的显示程度是Information级别.

最后还要在OnConfiguring方法里告诉modelBuilder使用MyLoggerFactory作为LoggerFactory.

这就配置好了.

插入数据.

这部分很简单, 打开UI项目的Program.cs:

Entity Framework Core 2.0 入门

这里都懂的, 创建好model之后, 添加到context的DbSet属性里, 这时context就开始追踪这个model了.

SaveChanges方法, 会检查所有被追踪的models, 读取他们的状态. 这里用到是Add方法, context就会知道这个model的状态是new, 所以就应该被插入到数据库. 然后它就根据配置会生成出相应的sql语句, 然后把这个SQL语句执行到数据库. 如果有返回数据的话, 就取得该数据.

下面就运行一下这个console程序:

dotnet run --project=./LearnEf.UI

看下控制台:

Entity Framework Core 2.0 入门

可以看到输出了sql语句, 而且这个出入动作后, 做了一个查询把插入数据生成的Id取了回来.

默认情况下log不显示传进去的参数, 这是为了安全. 但是可以通过修改配置来显示参数:

Entity Framework Core 2.0 入门

然后控制台就会显示这些参数了:

Entity Framework Core 2.0 入门

批量插入操作.

Entity Framework Core 2.0 入门

可以使用AddRange添加多条数据. 其参数可以是params或者集合.

可以看到这个和之前Add的Sql语句是完全不同的:

Entity Framework Core 2.0 入门

这个语句我不是很明白.

批量添加不同类型的数据:

Entity Framework Core 2.0 入门

使用context的AddRange或Add方法, DbContext可以推断出参数的类型, 并执行正确的操作. 上面的方法就是使用了DbContext.AddRange方法, 一次性添加了两种不同类型的model.

这两个方法对于写一些通用方法或者处理复杂的情况是很有用的.

Sql Server对于批量操作的限制是, 一次只能最多处理1000个SQL命令, 多出来的命令将会分批执行.

如果想更改这个限制, 可以这样配置参数:

Entity Framework Core 2.0 入门

简单查询.

针对DbSet, 使用Linq的ToList方法, 会触发对数据库对查询操作:

首先把Company的ToString方法写上:

Entity Framework Core 2.0 入门

这样方便输入到控制台.

然后写查询方法:

Entity Framework Core 2.0 入门

看结果:

Entity Framework Core 2.0 入门

EfCore到查询有两类语法, 一种是Linq方法, 另一种是Linq查询语法:

这种是Linq方法:

Entity Framework Core 2.0 入门

下面这种是Linq查询语法:

Entity Framework Core 2.0 入门

我基本都是使用第一种方法.

除了ToList(Async)可以触发查询以外, 遍历foreach也可以触发查询:

Entity Framework Core 2.0 入门

但是这种情况下, 可能会有性能问题. 因为:

在遍历开始的时候, 数据库连接打开, 并且会一直保持打开的状态, 直到遍历结束.

所以如果这个遍历很耗时, 那么可能会发生一些问题.

最好的办法还是首先执行ToList, 然后再遍历.

查询的过滤.

这部分和以前的EF基本没啥变化.

Entity Framework Core 2.0 入门

这个很简单, 不说了.

这里列一下可触发查询的Linq方法:

Entity Framework Core 2.0 入门

还有个两个方法是DbSet的方法, 也可以触发查询动作:

Entity Framework Core 2.0 入门

上面这些方法都应该很熟悉, 我就不写了.

过滤的条件可以直接家在上面的某些方法里面, 例如:

Entity Framework Core 2.0 入门

通过主键查询, 就可以用DbSet的Find方法:

Entity Framework Core 2.0 入门

这个方法有个优点, 就是如果这条数据已经在Context里面追踪了, 那么查询的时候就不查数据库了, 直接会返回内存中的数据.

EF.Functions.Like 这个方法是新方法, 就像是Sql语句里面的Like一样, 或者字符串的Contains方法:

Entity Framework Core 2.0 入门

这个感觉更像Sql语句, 输出到Console的Sql语句如下:

Entity Framework Core 2.0 入门

这里还要谈的是First/FirstOrDefault/Last/LastOrDefaut方法.

使用这些方法必须先使用OrderBy/OrderByDescending排序. 虽然不使用的话也不会报错, 但是, 整个过程就会变成这样, context把整个表的数据家在到内存里, 然后返回第一条/最后一条数据. 如果表的数据比较多的话, 那么就会有性能问题了.

更新数据.

Entity Framework Core 2.0 入门

很简单, context所追踪的model属性变化后, SaveChanges就会更新到数据库.

当然, 多个更新操作和插入等操作可以批量执行.

离线更新.

Entity Framework Core 2.0 入门

就是这种情况, 新的context一开始并没有追踪one这个数据. 通过使用Update方法, 追踪并设置状态为update. 然后更新到数据库.

Entity Framework Core 2.0 入门

可以看到, 在这种情况下, EfCore会更新该model到所有属性.

Update同样也有DbSet的UpdateRange方法, 也有context到Update和UpdateRange方法, 这点和Add是一样的.

还有一种方法用于更新, 这个以后再说.

删除数据.

DbContext只能删除它追踪的model.

Entity Framework Core 2.0 入门

非常简单, 从log可以看到, 删除动作只用到了主键:

Entity Framework Core 2.0 入门

如果是删除的离线model, 那么Remove方法首先会让Dbcontext追踪这个model, 然后设置状态为Deleted.

删除同样有RemoveRange方法.

Raw SQL查询/命令:

这部分请看文档:

命令: DbContext.Database.ExecuteSqlCommand();

Entity Framework Core 2.0 入门

Entity Framework Core 2.0 入门

查询: DbSet.FromSql() https://docs.microsoft.com/en-us/ef/core/querying/raw-sql;

这个方法目前还有一些限制, 它只能返回实体的类型, 并且得返回domain model所有的属性, 而且属性的名字必须也得一一对应. SQL语句不可以包含关联的导航属性, 但是可以配合Include使用以达到该效果(https://docs.microsoft.com/en-us/ef/core/querying/raw-sql#including-related-data).

Entity Framework Core 2.0 入门

Entity Framework Core 2.0 入门

更多的传递参数方式还需要看文档.

查询和保存关联数据.

插入关联数据.

我之前忘记在Department里面添加Name字段了, 现在添加一下, 具体过程就不写了.

插入关联数据有几种情况:

1.直接把要添加的Model的导航属性附上值就可以了, 这里的Department不需要写外键.

Entity Framework Core 2.0 入门

看一下Sql:

Entity Framework Core 2.0 入门

这个过程一共分两步: 1 插入主表, 2,使用刚插入主表数据的Id, 插入子表数据.

2.为数据库中的数据添加导航属性.

Entity Framework Core 2.0 入门

这时, 因为该数据是被context追踪的, 所以只需在它的导航属性添加新记录, 然后保存即可.

3.离线数据添加导航属性.

这时候就必须使用外键了.

Entity Framework Core 2.0 入门

预加载关联数据 Eager Loading.

也就是查询的时候一次性把数据和其导航属性的数据一同查询出来.

Entity Framework Core 2.0 入门

看看SQL:

Entity Framework Core 2.0 入门

这个过程是分两步实现的, 首先查询了主表, 然后再查询的子表. 这样做的好处就是性能提升.

(FromSql也可以Include).

预加载子表的子表:

可以使用ThenInclude方法, 这个可以老版本ef没有的.

Entity Framework Core 2.0 入门

这里查询Department的时候, 将其关联表Company也查询了出来, 同时也把Company的关联表Owner也查询了出来.

查询中映射关联数据.

Entity Framework Core 2.0 入门

使用Select可以返回匿名类, 里面可以自定义属性.

这个匿名类只在方法内有效.

看下SQL:

Entity Framework Core 2.0 入门

可以看到SQL中只Select了匿名类里面需要的字段.

如果需要在方法外使用该结果, 那么可以使用dynamic, 或者建立一个对应的struct或者class.

使用关联导航属性过滤, 但是不加载它们.

Entity Framework Core 2.0 入门

SQL:

Entity Framework Core 2.0 入门

这个比较简单. 看sql一切就明白了.

修改关联数据.

也会分两种情况, 被追踪和离线数据.

被追踪的情况下比较简单, 直接修改关联数据的属性即可:

Entity Framework Core 2.0 入门

看一下SQL:

Entity Framework Core 2.0 入门

确实改了.

这种情况下, 删除关联数据库也很简单:

Entity Framework Core 2.0 入门

看下SQL:

Entity Framework Core 2.0 入门

删除了.

下面来看看离线状态下的操作.

Entity Framework Core 2.0 入门

这里需要使用update, 把该数据添加到context的追踪范围内.

看一下SQL:

Entity Framework Core 2.0 入门

这个就比较怪异了.

它update了该departmt和它的company以及company下的其他department和company的owner. 这些值倒是原来的值.

这是因为, 看上面的代码, 查询的时候department的关联属性company以及company下的departments和owner一同被加载了.

尽管我只update了一个department, 但是efcore把其他关联的数据都识别出来了.

从DbContext的ChangeTracker属性下的StateManger可以看到有多少个变化.

这一点非常的重要.

如何避免这个陷阱呢?

可以这样做: 直接设置dbContext.Entry().State的值

Entity Framework Core 2.0 入门

这时, 再看看SQL:

Entity Framework Core 2.0 入门

嗯. 没错, 只更新了需要更新的对象.

2.1版本将于2018年上半年发布, 请查看官网的路线图: https://github.com/aspnet/EntityFrameworkCore/wiki/roadmap

完.

上一篇:50个Android开发技巧(03 自己定义ViewGroup)


下一篇:解决python查询报%d format: a number is required, not str问题