EF联合查询,如何设置条件过滤从表数据
最近在使用EF进行联合查询过程中,遇到了一件不开心的事情。
已禁用懒加载
var post = await _repository.GetMyPostById(blogId, postId).AsNoTracking()
.Include(p => p.PostToCategories)
.SingleOrDefaultAsync();
如上代码所示的查询中,使用Include()关联了PostToCategories,这是常用的联合查询方式。可是PostToCategories是软删除(IsAcitve)的,使用Include()方法会把所有的相关的PostToCategories都查询出来,这不是我们想要的结果。
首先分析下原因,Include()方法,是根据配置的关系查询关联的对象,所以我们只要在它生成sql之前加上过滤条件就可以了,可是纵观EF的api,无一能实现目的。既然这样,我们只能想想其他办法了。
var post = await _repository.GetMyPostById(blogId, postId).AsNoTracking()
.Select( p => new {
BlogPost = p,
PostToCategories = p.PostToCategories.Where(c => c.IsActive)
}).SingleOrDefaultAsync();
var blogPost = post.BlogPost;
blogPost.PostToCategories = post.PostToCategories.ToList();
用匿名类型接受主表和从表的查询结果,这样就可以为从表设置过滤条件了。最后,把匿名结果显示赋值给blogPost。
通过观察生成的sql语句,我们发现确实是在 ` join PostToCategories ` 后面增加了where条件。
但是这种方法在面对多对多关系时,就**不够优雅**了。
var post = await _repository.GetMyPostById(blogId, postId).AsNoTracking()
.Include(p => p.TagMap)
.Include(p => p.TagMap.Select(t => t.Tag))
.SingleOrDefaultAsync();
改写成如下:
var post = await _repository.GetMyPostById(blogId, postId).AsNoTracking()
.Select( p => new {
BlogPost = p,
TagMap = p.TagMap,
Tag = p.TagMap.Select(t => t.Tag),
}).SingleOrDefaultAsync();
var blogPost = post.BlogPost;
blogPost.TagMap = post.TagMap;
blogPost.TagMap.ForEach(m => m.Tag = post.Tag.FirstOrDefault(g => g.Id == m.TagId));
是不是感觉不美好了?
那有没有更好的办法呢?stackoverflow上有人推荐了一个针对EF的扩展包 EntityFramework.DynamicFilters ,它的实现方式是在OnModelCreating的时候给Entity设置好过滤条件,当前DbContext对象涉及到该Entity类型的查询时,都会自动加上过滤条件。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Filter("PostToCategory_IsActive", (PostToCategory ptc) => ptc.IsActive, true);//为PostToCategory类型设置过滤条件:IsActive==true
}
直接使用Include()就可以得到我们想要的结果,如下所示:
var post = await _repository.GetMyPostById(blogId, postId).AsNoTracking()
.Include(p => p.PostToCategories)
.SingleOrDefaultAsync();
可是这样以来所有的涉及到PostToCategories的查询都会被过滤,怎么办呢?EntityFramework.DynamicFilters提供 禁用/启动 过滤条件的API
context.DisableFilter/EnableFilter("PostToCategory_IsActive");// 在当前DbContext实例对象中禁用/启用名为PostToCategory_IsActive的Filter
modelBuilder.DisableFilterGlobally("PostToCategory_IsActive");// 全局禁用名为PostToCategory_IsActive的Filter
context.DisableAllFilters();//禁用所有的Filters
context.EnableAllFilters(); //启用所有的Filters
于是代码就变成了这样:
一、设置Filter
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Filter("PostToCategory_IsActive", (PostToCategory ptc) => ptc.IsActive, true);//为PostToCategory类型设置过滤条件:IsActive==true
}
二、全局禁用Filters
context.DisableAllFilters();
三、在需要过滤的地方启用Filter
context.EnableFilter("PostToCategory_IsActive");
var post = await _repository.GetMyPostById(blogId, postId).AsNoTracking()
.Include(p => p.PostToCategories)
.SingleOrDefaultAsync();
而且还没有考虑DbContext缓存查询结果带来的问题。
如果说第一种解决方案不优雅,那么这种方案就是恶心。
--- 2016.10.10 ---
昨天借鉴了ABP的封装思想,把EntityFramework.DynamicFilters的API封装了下,确实美观多了。
参见:
本来顺风顺水,如tkb至简的博文中描述的那样,优雅的过滤数据,可惜最后在一次保存的时候出现了意外,最后发现原因出在和EntityFramework.Extended有冲突,因为后者是重新生成了SqlExpression,没有对EntityFramework.DynamicFilters在设置where条件中的@DynamicFilterParam_000001赋值。
暂时没有想到更好的办法,遂先滚回去。:(
EF联合查询,如何设置条件过滤从表数据的更多相关文章
- EF联合查询的新用法
用EF很多年了,做联合查询时,只知道linq和lambda两种语法,今天朋友发了一个链接,打开看后发现是EF内置的新的关于联合查询的方法,赶紧抄录下来,以备后用. 现在先把这几种方法,各写一个例子,便 ...
- Left Join on 多条件查询时,条件过滤的问题
例如:A Left Join B on (...) on 后面的条件是对B数据的过滤,如果要对A的数据或者联合之后的数据集进行过滤,则要把过滤条件放在where子句中
- EF 联合查询
EF 文章表和标签表联合查询标签id在dis中的文章,还不知道性能如何 var query = tagRepo.Entities.Include("Tags").Where(t = ...
- LINQ,EF联合查询join
public object GetListAdmin() { //return db_C56.Admins // .Where(a => a.Status != "D") ...
- SQL Server -- 回忆笔记(二):增删改查,修改表结构,约束,关键字使用,函数,多表联合查询
SQL Server知识点回忆篇(二):增删改查,修改表结构,约束,关键字使用,函数,多表联合查询 1. insert 如果sql server设置的排序规则不是简体中文,必须在简体中文字符串前加N, ...
- SharePoint 列表多表联合查询
在SharePoint平台二次开发中,我们有时需要涉及多表关联查询展示多列表中的不同字段信息:SharePoint和Sql数据表一样,也支持多表联合查询,但是不像Sql语句那样简单,有一定的局限性,需 ...
- mysql之连接查询、联合查询、子查询
本文内容: 连接查询 联合查询 子查询 from子查询 where子查询 exists子查询 首发日期:2018-04-11 连接查询: 连接查询就是将多个表联合起来查询,连接查询方式有内连接.外连接 ...
- MyBatis 多表联合查询及优化 以及自定义返回结果集
下面就来说一下 mybatis 是通过什么来实现多表联合查询的.首先看一下表关系,如图: 这 里,我已经搭好了开发的环境,用到的是 SpringMVC + Spring + MyBatis,当然,为了 ...
- baby sqli 联合查询加入数据 手工注入
0x00 BabySQli 原题目描述:刚学完sqli,我才知道万能口令这么危险,还好我进行了防护,还用md5哈希了密码! 登陆页面,查看源码后点进search.php看到一段可疑的句子MMZFM42 ...
随机推荐
- NOIP主要考查范围
基本数据结构 栈 队列 数组 优先队列 中级数据结构 堆(大根堆,小根堆) 并查集和带权并查集 哈希表 高级数据结构 (可选学) 树状数组 线段树 各种其他树 字符串和相关内容 1.KMP 2.各种操 ...
- jQuery获取输入框并设置焦点
$(':input:enabled:visible:first').focus(); $("input:text:visible:first").focus(); 表单元素选择器: ...
- [MS SQL Server]SQL Server如何开启远程访问
在日常工作中,经常需要连接到远程的MS SQL Server数据库中.当然也经常会出现下面的连接错误. 解决方法: 1. 设置数据库允许远程连接,数据库实例名-->右键--->属性---C ...
- Git - 问题集
1.If no other git process is currently running, this probably means a git process crashed in this re ...
- OpenLayers 3 之 地图样式(ol.style)详解
地图样式是由 style 类控制的,其包含了地图样式的方方面面,例如,填充色.图标样式.图片样式.规则图形样式.边界样式.文字样式等,样式一般针对矢量要素图层. 矢量图层样式可以事先写好,写成静态的, ...
- DFS序+线段树 hihoCoder 1381 Little Y's Tree(树的连通块的直径和)
题目链接 #1381 : Little Y's Tree 时间限制:24000ms 单点时限:4000ms 内存限制:512MB 描述 小Y有一棵n个节点的树,每条边都有正的边权. 小J有q个询问,每 ...
- Oracle 查询出来的数据取第一条
Oracle 查询出来的数据取第一条 --------------------------------------------------------------------------- 转载自:h ...
- js和css文件压缩
压缩网址 http://tool.chinaz.com/tools/jscodeconfusion.aspx http://tool.oschina.net/jscompress?type=3 htt ...
- 浅谈我对 jQuery 的了解
总述 0 获取 jQuery 对象 1 对象跳转 2 方法调用 3 常用API 4 $(…); 5 jQuery 对象获取 6 Data 相关方法 7 选择器 8 基本的过滤器 9 内容过滤选择器 1 ...
- asp.net两种方式的短信接口使用(提供接口的都是收费的)
一种是http请求的方式,另一种就是提供WebService接口供调用的. //服务商 sms.webchinese.cn //sms_url="http://sms.webchinese. ...