1

对不起我糟糕的英语。

我正在尝试扩展我的 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;
    }
//[...]
}

...使用表达式 HasMetas 扩展实体“vit_post”。

使用这个片段,我得到了实体的一个子集,正如预期的那样:

    public SearchResults GetResults()
    {
            var query = dbc.vit_posts.AsExpandable();
    //[...]
            if (SearchArgs.Metas != null)
            {
                var postsbycontent = vit_post.HasMetas(SearchArgs.Metas);
                outer = Data.Utility.And(outer, postsbycontent);
            }
    //[...]
            query = query.Where(outer);

            var searchResults = new SearchResults
                        {
                            Items = searchResultsItems
                        };

            return searchResults;
    }

但是,如果我尝试将此表达式移动到像这样的“vit_postmeta”实体:

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;
//[...]
}

我的想法是将原始方法保留在 vit_post 中并像这样进行更改:

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_postmeta' 不包含'HasMetas' 的定义,并且找不到接受'vit_postmeta' 类型的第一个参数的扩展方法'HasMetas'”。

我错过了一些东西,我知道,但我找不到什么。

更新

我找到了一种替代解决方案(也许也是正确的解决方案),在各自的实体部分类中实现我的所有表达式。例如, vit_post 具有与 vit_posts 表相关的所有表达式,而 vit_postmeta 具有与 vit_postmeta 表相关的所有表达式。

然后,我的 Search 类对每个实体都有一个私有方法。就像是:

            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);
                }
    [...]
    }

然后 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;
                }

        }

这样我可以使查询工作,但我仍然不确定这是正确的方法。

4

1 回答 1

0

您还没有看到/回答我的问题,但是如果vit_postmeta并且vit_post以任何方式与继承相关,您可以执行以下操作:

public static Expression<Func<T, bool>> HasMetas<T>(IEnumerable<MetaFilter> metaArgs)
    where T : vit_post
{
    ...
}

假设这vit_post是超级类型。

于 2011-09-18T18:00:31.887 回答