这是我的模型
class Parent
{
int Id;
string Name;
List<Child> Childs;
} // name is unique
class Child
{
int Id;
int ParentId;
string Name;
Parent Parent;
} // couple (id, name) is unique
对于给定的夫妇列表(父姓名,子姓名),我想得到夫妇(父姓名,子姓名),如果父姓名存在,而子姓名不存在,那么子姓名可以为空。sql查询如下所示:
SELECT *
FROM parents p
LEFT JOIN childs c ON c.parent_id = p.id
WHERE p.name = 'parent1' AND (c.name IS NULL OR c.name = 'child1')
OR p.name = 'parent2' AND (c.name IS NULL OR c.name = 'child2')
OR p.name = 'parent3' AND (c.name IS NULL OR c.name = 'child3')
OR p.name = 'parent4' AND (c.name IS NULL OR c.name = 'child4');
我尝试过用实体框架核心表示这个查询,使用predicatebuilder表示or和false方法
var predicate = PredicateBuilder.False<Parent>()
.Or(p => p.Name == "parent1" && p.Childs.Any(c => c.Name == "child1"))
.Or(p => p.Name == "parent2" && p.Childs.Any(c => c.Name == "child2"))
.Or(p => p.Name == "parent3" && p.Childs.Any(c => c.Name == "child3"))
.Or(p => p.Name == "parent4" && p.Childs.Any(c => c.Name == "child4"));
var p = await _db.Parents
.Include(p => p.Childs)
.Where(predicate)
.ToArrayAsync();
这是我能得到的最接近的结果,但这没有得到预期的结果:
如果子级不存在,则父级不在结果集中 Parent.Childs
包含父级的所有子级,而不是只包含所需的子级
我的查询可以用实体框架核心表达吗?
2条答案
按热度按时间cbeh67ev1#
根据你的意见,现在的要求是:给我所有的父母,按姓名指定,每个父母只有一个特定的孩子,如果有的话。也就是说:有其他孩子的父母会出现在结果中,但没有孩子。
这听起来很琐碎,但事实并非如此。问题是它需要两个过滤器,一个在父过滤器上,一个在子过滤器上,其中子过滤器甚至是特定于父过滤器的。sql查询如下所示:
对于ef linq查询,父 predicate 可以是一个简单的
Contains
,但您希望使用 predicate 生成器构建 predicate 。在这里,出于后面的原因,我使用linqkit.core。为了能够从一个源构建 predicate ,我使用了一个临时结构(但我猜您已经有了类似的结构):
准备 predicate :
现在,理想情况下,linq查询应该是这样的(
db
是一个上下文),工作中缺少过滤Include
:但那不是因为
p.Children
是IEnumerable
,所以childPredicateStarter
隐式转换为Func
而不是必需的Expression<Func>>
. 请参阅此处以获得深入的解释。实际工作版本为:
这个
AsExpandable
调用转换Invoke
返回到一个适当的表达式树中,ef可以将其转换为sql。wrrgggsh2#
parent.childs包含父级的所有子级,而不是只包含所需的子级
筛选包含即将到来,但尚未实现。我有点不明白为什么你认为它实际上会过滤,因为你的代码清楚地说明了所有的孩子。。。
.include(p=>p.childs)
意思是包括孩子(顺便说一句,childs是蹩脚英语-复数是childs)。那里没有过滤器。
有关过滤的信息包括:
过滤包含在ef核心中
在此引用相关部分:
“最后,此功能已从ef core preview版本5.0.0-preview.3.20181.2开始实施,并将在ef core版本5.0.0中正式推出。”
但即使这样,您也必须进行过滤(即ptut a where into the include,而不仅仅是告诉它获取所有这些内容)。