Entity Framework之问题收集

本节讨论内容主要针对收集了上篇文章大家碰到问题的讨论解决,会持续收集扩充。

  • DbContext加载原值,当前值,数据库值,属性操作,对象复制,对象值复制(VO,DTO->POCO),复杂对象取值
  • DbContext Local Data与AsNoTracking无跟踪查询 如何提高效率
  • DbContext如何关闭延迟加载
  • DbContext如可使用延迟加载
  • DbContext如何控制并发
  • 解除属性映射到数据库中
  • 对象失去或没有被跟踪时处理
  • 多对多关系之扩展字段字段处理
  • 利用模板使模型继承基类
  • 如何对象模型中使用枚举值
  • 创建或使用代理对象
  1. DbContext加载原值,当前值,数据库值,属性操作,对象复制,对象值复制(VO,DTO->POCO),复杂对象取值

View Code

  1. DbContext Local Data与AsNoTracking无跟踪查询 提高效率

Local Data是通过Load()方法将数据下载到本地,并与Context保持联系,以提高查询效率或者解决批量操作等问题。

View Code

重写DbContext SaveChanges方法阻止Local Data数据更新

View Code

AsNoTracking无跟踪查询

View Code

批量操作关闭自动检测提高效率

View Code

  1. DbContext如何关闭开启延迟加载

关闭方式

View Code

加载方式

View Code

  1. DbContext如何控制并发

乐观并发的控制

View Code

即使使用Timestamp字段,我们一样也是通过乐观并发控制,然后较验timestamp字段是否一致,或者通过存储过程实现这一过程。

  1. 解除属性映射到数据库中

EF 提供了一系列属性用于描述模型

  • KeyAttribute

  • StringLengthAttribute

  • MaxLengthAttribute

  • ConcurrencyCheckAttribute

  • RequiredAttribute

  • TimestampAttribute

  • ComplexTypeAttribute

  • ColumnAttribute

  • TableAttribute

  • InversePropertyAttribute

  • ForeignKeyAttribute

  • DatabaseGeneratedAttribute

  • NotMappedAttribute
    可以通过NotMappedAttribute标记模型某个属性可以使该属性不必映射到数据库。

    View Code

另外我们还可以通过代码的方式,在DbContext的OnModelCreating方法重载中实现,不知道用Code First的人为什么喜欢这种方式处理。DbContext默认是把EDMX文件当成EntityConfiguration加载进来的,和手动处理这些映射关系是一样的。但是手动处理大量的映射关系既不直观,也不容易维护,而EDMX这个模型视图浏览与维护都较之方便啊。

View Code

EDMX怎么解除映射还没有找到如何实现,删除表映射EDM验证无法通过,而对象属性又没提供NotMapped 选择。

我觉得如果一个属性不需要映射到数据库时,那这个POCO对象设计肯定是不合理的,可能他是一个合理VO对象,或者是数据库查询视图对象。

  1. 对象失去或没有被跟踪时处理

context.Set<BlogArticle>().Attach() 加回上下文中,继续跟踪

  1. 多对多关系之扩展字段字段处理

EF 处理多对多关系,是通过中间表主外键关联加载对应的主体表对象,这个中间表是个不存在的业务对象。而中间表如果除了主外键之外还有扩展的字段,就会导致中间表变成一个具体存在的业务对象,让它成为对应主体表的关联导航属性。因此这种中间表设计是不合理,但EF可以应对这种情况。看下图

Student<-Score(多对多中间表)->Subject 三个对象 由于Score不是一个合理的中间表,导致EF将其映射为一个具体的实体对象成为Student与Subject的导航属性。

而User<-UserProperty(多对多中间表)->Property UserProperty仅是数据关系的体现,并不是一个具体的实体对象,User与Property是直接导航。

  1. 利用模板使模型继承基类

由于我们的纯POCO模型没有基类限制领域,所以在我们的泛型传递POCO的对象给DAL时,就无法限制这个T 是POCO对象呢,还是其它的对象。因此为了将POCO对象与其它业务对象区分开来,可以通过使POCO对象继承一个基类来解决这个问题,当然肯定是模板解决这个问题了。

我们先立一个POCOEntity基类

View Code

再打DemoDB.tt 模版,找到这段代码(或者直接搜索partial),修改为:

View Code

即在模版生成类结构代码追加其继承POCOEnity基类,修改完成后,点击保存,所有模型类会重新生成,我们看一下生成后的代码

View Code

这个时候我们就可以控制DAL传入的泛型模型参数T的域范围了

public interface IRepository<T> where T : POCOEnity, new()

public abstract class RepositoryBase<T>:IRepository<T> where T :POCOEnity,new()

  1. 如何对象模型中使用枚举值

插件: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=26660

昨晚整了一下,整个VS2010打完补丁后,所有模板都出现2个,程序集还不一致。-_-|||悲剧,看一下微软ADO.NET 团队博客的图

想自己实现的朋友,可以参照ADO.NET TEAM的BLOG。我觉得枚举就是一个转换的过程,不一定非要通过枚举实现,毕竟整个项目用的枚举很多,而这些枚举肯定是存放在一张表里,而不是一个枚举一张表一个对象,若是这样处理起来肯定是给自己增加麻烦。

  1. 创建或使用代理对象

首先开启代理会影响到实体对象的序列化操作(可能无法序列化),但是禁用代理又无法延迟加载导航数据。延迟加载无非是访问这个属性时会自动加载导航属性数据,如果项目需要对象序列化,我们可以禁用代理并闭延迟加载以提高效率,当需要使用导航属性可以使用DbContext.Entity 加载导航数据。

禁用代理对象this.Configuration.ProxyCreationEnabled = false;

当New一个模型时 BlogCategory cate = new BlogCategory(); 则是创建实体对象

而通过DbSet<POCO>.Create() ,则是显示创建代理。

相关推荐
啵啵鱼爱吃小猫咪1 小时前
Franka机械臂安装实时内核
数据库·postgresql
今天也是元气满满的一天呢2 小时前
从单机架构到负载均衡的互联网架构全流程
数据库·系统架构
SelectDB2 小时前
快手 AB 场景提速 145 倍,从 Spark 到 Apache Doris 的加速实践
数据库·spark·开源
SelectDB2 小时前
阶跃星辰 Agent 可观测实践:为什么 Trace 数据底座选择 SelectDB?
大数据·数据库·agent
冷静的楼房2 小时前
使用ThreadPool发起同步的调用
数据库
一个天蝎座 白勺 程序猿2 小时前
自动SQL优化实战|吃透调优接口+报告配置+统计+索引全流程落地
数据库·sql·sql优化
TDengine (老段)2 小时前
# TDengine TMQ 最佳实践 — 可靠消费、容错与监控
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
杨云龙UP3 小时前
Windows SQL Server 备份无法传输至异地共享目录排查处理
运维·服务器·数据库·windows·共享·smb·异地备份传输
落寞的电源3 小时前
Delegate = Object + MethodInfo
开发语言·数据库·c#