Linq 实体框架:混合实体的混合谓词
对不起,我的英语糟透了 我正在尝试扩展我的EF模型(使用LinqKit) 只要我使用单实体表达式,我就不会有任何问题,但是如果我想使用混合表达式,我只是被卡住了 例如,像这样的一种后课堂Linq 实体框架:混合实体的混合谓词,linq,c#-4.0,entity-framework-4,linqkit,Linq,C# 4.0,Entity Framework 4,Linqkit,对不起,我的英语糟透了 我正在尝试扩展我的EF模型(使用LinqKit) 只要我使用单实体表达式,我就不会有任何问题,但是如果我想使用混合表达式,我只是被卡住了 例如,像这样的一种后课堂 partial class vit_post { //[...] public static Expression<Func<vit_post, bool>> HasMetas(IEnumerable<MetaFilter> metaArgs) {
partial class vit_post
{
//[...]
public static Expression<Func<vit_post, bool>> HasMetas(IEnumerable<MetaFilter> metaArgs)
{
var resultsInner = PredicateBuilder.True<vit_post>();
resultsInner.And(p=>p.vit_postmeta.Any(pm => (pm.hide == false)));
foreach (var metaArg in metaArgs)
{
var mf = metaArg;
resultsInner.And(p=>p.vit_postmeta.Any(pm => (pm.meta_key == mf.MetaKey && mf.Compare(pm.meta_value))));
if (mf.ChildrenMetaFilters != null)
{
Expression<Func<vit_post, bool>> resultsInner2;
switch (mf.LogicalOperator)
{
case LogicalOperators.AND:
resultsInner2 = PredicateBuilder.True<vit_post>();
resultsInner = resultsInner2.And(HasMetas(mf.ChildrenMetaFilters));
break;
case LogicalOperators.OR:
resultsInner2 = PredicateBuilder.False<vit_post>();
resultsInner = resultsInner2.Or(HasMetas(mf.ChildrenMetaFilters));
break;
}
}
}
return resultsInner;
}
//[...]
}
但是如果我试着把这个表达式移到“vit_posteta”实体,像这样:
partial class vit_postmeta
{
//[...]
var resultsInner = PredicateBuilder.True<vit_postmeta>();
resultsInner.And(pm => (pm.hide == false));
foreach (var metaArg in metaArgs)
{
var mf = metaArg;
resultsInner.And(pm => (pm.meta_key == mf.MetaKey && mf.Compare(pm.meta_value)));
if (mf.ChildrenMetaFilters != null)
{
Expression<Func<vit_postmeta, bool>> resultsInner2;
switch (mf.LogicalOperator)
{
case LogicalOperators.AND:
resultsInner2 = PredicateBuilder.True<vit_postmeta>();
resultsInner = resultsInner2.And(HasMetas(mf.ChildrenMetaFilters));
break;
case LogicalOperators.OR:
resultsInner2 = PredicateBuilder.False<vit_postmeta>();
resultsInner = resultsInner2.Or(HasMetas(mf.ChildrenMetaFilters));
break;
}
}
}
return resultsInner;
//[...]
}
partial class vit_post
{
//[...]
public static Expression<Func<vit_post, bool>> HasMetas(IEnumerable<MetaFilter> metaArgs)
{
var resultsInner = PredicateBuilder.True<vit_post>();
resultsInner.And(p=>p.vit_postmeta.HasMetas(metaArgs));
return resultsInner;
}
//[...]
}
部分等级vit_postETA
{
//[...]
var resultinner=PredicateBuilder.True();
resultsInner.And(pm=>(pm.hide==false));
foreach(元参数中的变量元参数)
{
var mf=metaArg;
resultsInner.And(pm=>(pm.meta_-key==mf.MetaKey&&mf.Compare(pm.meta_-value));
if(mf.ChildrenMetaFilters!=null)
{
表达结果ner2;
开关(mf.逻辑运算器)
{
case LogicalOperators.AND:
resultInner2=PredicateBuilder.True();
resultsInner=resultsInner2.And(HasMetas(mf.ChildrenMetaFilters));
打破
case LogicalOperators.OR:
resultInner2=PredicateBuilder.False();
resultsInner=resultsInner2.Or(HasMetas(mf.ChildrenMetaFilters));
打破
}
}
}
返回结果器;
//[...]
}
我的想法是在vit_post中保留原始方法,并将其更改为:
partial class vit_postmeta
{
//[...]
var resultsInner = PredicateBuilder.True<vit_postmeta>();
resultsInner.And(pm => (pm.hide == false));
foreach (var metaArg in metaArgs)
{
var mf = metaArg;
resultsInner.And(pm => (pm.meta_key == mf.MetaKey && mf.Compare(pm.meta_value)));
if (mf.ChildrenMetaFilters != null)
{
Expression<Func<vit_postmeta, bool>> resultsInner2;
switch (mf.LogicalOperator)
{
case LogicalOperators.AND:
resultsInner2 = PredicateBuilder.True<vit_postmeta>();
resultsInner = resultsInner2.And(HasMetas(mf.ChildrenMetaFilters));
break;
case LogicalOperators.OR:
resultsInner2 = PredicateBuilder.False<vit_postmeta>();
resultsInner = resultsInner2.Or(HasMetas(mf.ChildrenMetaFilters));
break;
}
}
}
return resultsInner;
//[...]
}
partial class vit_post
{
//[...]
public static Expression<Func<vit_post, bool>> HasMetas(IEnumerable<MetaFilter> metaArgs)
{
var resultsInner = PredicateBuilder.True<vit_post>();
resultsInner.And(p=>p.vit_postmeta.HasMetas(metaArgs));
return resultsInner;
}
//[...]
}
部分等级vit\u post
{
//[...]
公共静态表达式HasMetas(IEnumerable metaArgs)
{
var resultinner=PredicateBuilder.True();
结果内部和(p=>p.vit_postmeta.HasMetas(metaArgs));
返回结果器;
}
//[...]
}
但我不能这样做,因为“'vit_posteta'不包含'HasMetas'的定义,并且找不到接受第一个'vit_posteta'类型参数的扩展方法'HasMetas'
我知道我错过了什么,但我找不到什么
更新
我已经找到了另一种解决方案(也许也是正确的解决方案),在各自的实体分部类中实现我的所有表达式。
例如,vit_post的所有表达式都与vit_posts的表相关,而vit_Posteta的所有表达式都与vit_Posteta的表相关
然后,我的搜索类对每个实体都有一个私有方法。比如:
private IQueryable<vit_post> QueryPosts()
{
IQueryable<vit_post> queryPosts = VITContext.vit_posts.AsExpandable();
Expression<Func<vit_post, bool>> outerPredicate = PredicateBuilder.True<vit_post>();
if (!_searchArgs.IncludeExpiredPosts)
{
Expression<Func<vit_post, bool>> postsByExpiration = vit_post.ExcludeExpired();
outerPredicate = Data.Utility.And(outerPredicate, postsByExpiration);
}
if (_searchArgs.LocaleCode != null)
{
Expression<Func<vit_post, bool>> postsByLanguage = vit_post.HasLocaleCode(_searchArgs.LocaleCode);
outerPredicate = Data.Utility.And(outerPredicate, postsByLanguage);
}
[...]
}
public static Expression<Func<T, bool>> HasMetas<T>(IEnumerable<MetaFilter> metaArgs)
where T : vit_post
{
...
}
private IQueryable QueryPosts()
{
IQueryable queryPosts=VITContext.vit_posts.AsExpandable();
表达式outerPredicate=PredicateBuilder.True();
如果(!\u searchArgs.IncludeExpiredPosts)
{
表达式postsbyexpntiation=vit_post.excludeExpirated();
outerPredicate=Data.Utility.And(outerPredicate,PostsByExperation);
}
如果(_searchArgs.LocaleCode!=null)
{
表达式postsByLanguage=vit_post.HasLocaleCode(_searchArgs.LocaleCode);
outerPredicate=Data.Utility.And(outerPredicate,postsByLanguage);
}
[...]
}
然后,GetResults()函数调用所有这些方法并将它们连接起来:
internal string GetResults()
{
IQueryable<vit_post> queryPosts = QueryPosts();
if (_searchArgs.Metas != null)
{
IEnumerable<vit_postmeta> queryMetas = QueryMetas();
queryPosts = from p in queryPosts
join m in queryMetas
on new {id = p.ID, loc = p.locale} equals new {id = m.post_id, loc = m.locale}
select p;
}
}
内部字符串GetResults()
{
iQueryPosts=queryPosts();
如果(_searchArgs.Metas!=null)
{
IEnumerable queryMetas=queryMetas();
queryPosts=来自queryPosts中的p
在queryMetas中加入m
在新的{id=p.id,loc=p.locale}上等于新的{id=m.post\u id,loc=m.locale}
选择p;
}
}
这样我可以使查询正常工作,但我仍然不确定这是正确的方法。您还没有看到/回答我的问题,但是如果
vit\u postemta
和vit\u post
通过继承以任何方式关联,您可以执行以下操作:
private IQueryable<vit_post> QueryPosts()
{
IQueryable<vit_post> queryPosts = VITContext.vit_posts.AsExpandable();
Expression<Func<vit_post, bool>> outerPredicate = PredicateBuilder.True<vit_post>();
if (!_searchArgs.IncludeExpiredPosts)
{
Expression<Func<vit_post, bool>> postsByExpiration = vit_post.ExcludeExpired();
outerPredicate = Data.Utility.And(outerPredicate, postsByExpiration);
}
if (_searchArgs.LocaleCode != null)
{
Expression<Func<vit_post, bool>> postsByLanguage = vit_post.HasLocaleCode(_searchArgs.LocaleCode);
outerPredicate = Data.Utility.And(outerPredicate, postsByLanguage);
}
[...]
}
public static Expression<Func<T, bool>> HasMetas<T>(IEnumerable<MetaFilter> metaArgs)
where T : vit_post
{
...
}
公共静态表达式HasMetas(IEnumerable metaArgs)
T:vit_post在哪里
{
...
}
假设vit_post是超级类型。什么让你觉得你的英语“糟糕”?阿杜奇:是。。。有时:)GertArnold:是的,vit_post与vit_Posteta有1-n关系(表格的设计与wordpress表格非常相似)。谢谢GertArnold。很抱歉,我没有收到关于您上一个问题的任何通知:也许我应该看看您的帐户设置。关于这个可能的解决方案,我有点困惑:我应该如何实现它?你能写一个例子吗(不一定基于我的代码)?@Andrea:我不确定我是否能写一个相关的例子,因为我不熟悉Linqkit,但我试图让你的表达式应用于一个类及其派生,而不是一个特定的类。我所建议的方法适用于常规扩展方法,但恐怕Linqkit有自己扩展类的方法。对于常规扩展方法,方法签名应该是类似于HasMetas的
HasMetas(这篇文章,IEnumerableI,请参阅)。在这种情况下,我并不真正需要扩展方法,因为我已经在文章表的一个部分类中工作了。不过,尽管出于其他目的,我会记住你的建议(真的,谢谢!),实际问题是如何实现多实体谓词表达式(使用LinqKit),以便根据用户的输入创建自定义查询。