2011-09-01 118 views
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; 
    } 
//[...] 
} 

...延伸的实体“vit_post”与表达HasMetas。

使用这个片段中,我得到了实体的一个子集,符合市场预期:

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'”。

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

UPDATE

我找到一个替代的解决方案(和或许是适当的一个太),实现在相应的实体部分类我的所有表达式。 例如,vit_post具有与vit_posts表相关的所有表达式,而vit_postmeta具有与vit_postmeta表相关的所有表达式。

我的搜索类,然后对每个实体的私有方法。喜欢的东西:

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

     } 

这样我可以让查询的工作,但我仍然不知道这是正确的方式来做到这一点。

+1

是什么让你觉得你的英语“很糟糕”? – Aducci

+0

Aducci:这是...有时:) –

+0

GertArnold:是的,vit_post有vit_postmeta 1-n的关系(表有非常相似的WordPress表设计)。 –

回答

0

你没看见/回答我的问题,但如果vit_postmetavit_post是继承关系的任何方式,您也许可以这样做:

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

假设vit_post是超类型。

+0

谢谢GertArnold。 对不起,我没有收到任何有关您之前的问题的通知:也许我应该看看tomy帐户设置。 关于这个可能的解决方案,我有点困惑:我是如何实现这个的? 你能写一个例子(不一定基于我的代码)? –

+0

@Andrea:我不确定能不能写一个相关的例子,因为我不熟悉Linqkit,但我试图让你的表达式适用于一个类及其衍生物,而不是仅仅一个特定的类。我建议使用常规的扩展方法,但恐怕Linqkit有它自己的扩展类的方法。使用常规的扩展方法,方法签名应该类似于'HasMetas (此T后,IEnumerable <...'。 –

+0

我看到了。 在这种情况下,我并不需要扩展方法,因为我已经但是,即使我将其他目的的建议记在心上(真的,谢谢!),但实际的问题是如何实现多实体谓词表达式(使用LinqKit ),以便根据用户的输入创建自定义查询。 –