2011-09-01 112 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 ),以便根據用戶的輸入創建自定義查詢。 –