2011-09-01 4 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 테이블과 관련된 모든 표현식이 있습니다.

내 검색 클래스에는 각 엔터티에 대한 개인 메서드가 있습니다. 뭔가 같은 : 다음

  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. 죄송합니다. 이전 질문에 대한 알림을받지 못했습니다. 아마 계정 설정이 잘못되었습니다. 이 가능한 솔루션에 대해 조금 혼란 스럽습니다. 어떻게 구현해야합니까? 예제를 작성할 수 있습니까? (필자의 코드를 기반으로 할 필요는 없습니까?) –

+0

@Andrea : Linqkit에 익숙하지 않아 관련 예제를 작성할 수 있는지는 잘 모르겠지만 단 하나의 특정 클래스 대신에 클래스와 파생 클래스에 표현식을 적용하려고했습니다. 필자가 제안한 것은 일반적인 확장 메서드를 사용하는 것이지만 Linqkit은 클래스를 확장하는 자체 방법을 가지고 있습니다. 정규 확장 메서드를 사용하면 메서드 서명이 HasMetas와 같아야합니다 (이 T 게시물, IEnumerable <...'. –

+0

참조). 이 경우에는 이미 확장 메서드가 필요하지 않습니다. 게시물의 테이블의 부분 클래스 내에서 작업합니다. 그러나 다른 목적을 위해 제안을 염두에 두 겠지만 (실제 감사합니다!), 실제 문제는 다중 엔티티 조건 자 표현식을 구현하는 방법입니다 (LinqKit)를 사용하여 사용자의 입력을 기반으로 사용자 지정 쿼리를 만듭니다. –