在数据库设计中这常被称作垂直分割。还是通过例子来看具体实现。我们给产品类增加2个新属性:
1 2 3 4 5 6 7 8 9 |
|
我们希望将新属性存储在另一张数据表中,可以按如下方式配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
代码一目了然,分开指定属性和相应的表即可。生成的迁移代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
是不是很眼熟,对!和之前配置1 - 1映射生成的迁移代码一模一样。当然生成的查询语句也是一样的。
将两个实体映射到一张表
我们把上一个例子中给Product增加的属性独立出来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
现在我们有2个实体类,接下来的配置将把它们映射到一张表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
生成的迁移代码可以看出,两个实体将被保存到一张表:
1 2 3 4 5 6 7 8 9 10 11 |
|
映射部分就到这里了。休息下吧。
中场休息
借中场休息时间鄙视一下那些转载不保留原链接的网站,尤其像numCTO这种。
变更跟踪
变更跟踪指的是对缓存于EF Context中的实体的状态的跟踪与改变。所以了解变更跟踪先看了解一下实体在EF Context中的几种状态。下面是国外某网站看到的一幅很不错的图,直接拿过来用了。
图3. EF Context中实体状态 来源
支持变更跟踪最关键的一点是实体必须有主键(如前文介绍通过Fluent API的HasKey<TKey>方法指定主键)。这样实体才能被EF Context这个缓存容器进行维护,并与数据库中相应的条目实现一一对应来支持增删改查。
变更跟踪是默认启用的,可以通过配置DbContext来关闭这个功能,如下代码:
1 |
|
注意:
一般来说不建议关闭变更跟踪,除非是只读(只读情况下用AsNoTracking获取实体并自己做缓存应该更好)。
在关闭变更跟踪的情况下,可以通过如下方法手动调用一次变更检测(或者用下文将介绍的手动状态改变),这样后续的SavaChanges操作才能正确完成。
1
context.ChangeTracker.DetectChanges();另外要注意的一点是,变更跟踪只能在一个上下文内有效。即如果有两个DbContext的实例,两个DbContext各自作用域内的变更跟踪是独立的。
除了使用自动变更跟踪,在对性能要求极端的情况下,也可以手动控制实体的状态(另一种情况是实体本不在当前Context中,要加入当前Context控制下必须手动完成)。
与实体变更控制最密切的就是DBEntityEntry类,这个类的对象正是通过前文介绍的DbContext的Entry<T>方法获得的。DBEntityEntry最重要的属性就是获取实体状态的State属性。
1 2 3 |
|
上面几行代码展示了查询与修改EF Context中实体状态的方法。
最后这段综合的代码示例演示了在关闭变更跟踪的情况下,手动修改实体状态实现更新。
1 2 3 4 5 6 |
|
AsNoTracking
对于只读操作,强烈建议使用AsNoTracking进行数据获取,这样省去了访问EF Context的时间,会大大降低数据获取的时间。
1 |
|
由于没有受EF Context管理,对于这样获取到的数据,更新的话需要先Attach然后手动修改状态并SaveChanges。
1 2 3 4 5 |
|