2011-09-01 11 views
1

ごめんなさい。エンティティフレームワーク:混合エンティティの混合述語

私は(LinqKitで)自分のEFモデルを拡張しようとしています。

私は単一のエンティティ式で作業している限り、私は問題はありませんが、混合式で作業したいのであれば、私はちょっと立ち往生しています。例えば

、そのようなソート・オブ・ポストクラス...

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」を拡張します。このスニペットを使用

、私は予想通り、実体のサブセットを取得:

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

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」エンティティにこのこの式を移動しようとした場合

私の考えは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のテーブルに関連するすべての式があります。

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

     } 

私は、クエリが動作することができます。この方法で、私はまだこれがわかりませんそれを行う正しい方法。

+1

あなたの英語は "ひどい"と思いますか? – Aducci

+0

Aducci:ときどき:) –

+0

GertArnold:はい、vit_postはvit_postmetaと1-nの関係を持っています(テーブルはWordPressのテーブルに非常に似たデザインです)。 –

答えて

0

あなたは/まだ私の質問に答えて見ませんでしたが、vit_postmetavit_postは継承によって関連するどのような方法である場合、あなたのような何かをすることができる場合がありますvit_postがスーパータイプであると仮定すると

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

を。

+0

GertArnoldありがとうございました。 申し訳ありませんが、あなたの以前の質問に関する通知はありませんでした。おそらく私はアカウントの設定を見てみるべきです。 この可能な解決策について、私はちょっと混乱しています:これを実装するにはどうすればいいですか? 例を書くことができますか(コードに基づいている必要はありません)? –

+0

@アンドレア:私はLinqkitに慣れていないので、関連する例を書くことができるかどうか分かりませんが、私はあなたの表現をクラスとその派生物に適用しようとしていました。私が示唆したことは、通常の拡張メソッドで動作するはずですが、Linqkitにはクラスを拡張する独自の方法があることを恐れています。通常の拡張メソッドでは、メソッドのシグネチャは 'HasMetas (このTポスト、IEnumerable <...'。 –

+0

)のようになります。 この場合、私はすでに拡張メソッドを必要としません。 しかし、私は他の目的のためにあなたの提案を心に留めていますが(本当に、ありがとう!)、実際の問題は、マルチエンティティの述語式を実装する方法です(LinqKit )を使用して、ユーザーの入力に基づいてカスタム照会を作成します。 –

関連する問題