Linq 实体框架:混合实体的混合谓词

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) {

对不起,我的英语糟透了

我正在尝试扩展我的EF模型(使用LinqKit)

只要我使用单实体表达式,我就不会有任何问题,但是如果我想使用混合表达式,我只是被卡住了

例如,像这样的一种后课堂

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),以便根据用户的输入创建自定义查询。