【问题标题】:Entity Framework: Mixed predicates of mixed entities实体框架:混合实体的混合谓词
【发布时间】:2011-09-19 15:42:30
【问题描述】:

对不起我糟糕的英语。

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

只要我使用单个实体表达式,我就没有任何问题,但如果我想使用混合表达式,我就会卡住。

例如,类似这样的 post-of-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.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”。

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

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

        }

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

【问题讨论】:

  • 是什么让你觉得你的英语“很糟糕”?
  • 阿杜奇:有时是…… :)
  • GertArnold:是的,vit_post 与 vit_postmeta 有 1-n 关系(表格的设计与 wordpress 表格非常相似)。

标签: linq c#-4.0 entity-framework-4 linqkit


【解决方案1】:

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

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

假设vit_post是超类型。

【讨论】:

  • 谢谢格特阿诺德。抱歉,我没有收到关于您之前的问题的任何通知:也许我应该看看我的帐户设置。关于这个可能的解决方案,我有点困惑:我应该如何实现这个?你能写一个例子吗(不一定基于我的代码)?
  • @Andrea:我不确定我是否可以写一个相关的例子,因为我不熟悉 Linqkit,但我试图让你的表达式适用于一个类及其派生类,而不是只有一个特定的类。我的建议适用于常规扩展方法,但我担心 Linqkit 有它自己的扩展类的方式。对于常规扩展方法,方法签名应该类似于HasMetas&lt;T&gt;(this T post, IEnumerable&lt;...。
  • 我明白了。在这种情况下,我真的不需要扩展方法,因为我已经在帖子表的部分类中工作。但是,即使我会记住您出于其他目的的建议(真的,谢谢!),实际问题是如何实现多实体谓词表达式(使用 LinqKit),以便根据用户的输入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 2014-11-27
相关资源
最近更新 更多