2014-12-20 2 views
0

내 프로젝트에서는 OrchardProject 웹 사이트에 this tutorial을 사용하여 레코드간에 N 대 N 관계를 구현했습니다. 나는 2 부분 : MaterialPart & CategoryPart 및 협회 기록이 있습니다.N-to-N 관계를 가진 과수원 CMS ContentQuery

재료 부분

public class MaterialPartRecord : ContentPartRecord { 
    public MaterialPartRecord() { 
     Categories = new List<ContentMaterialCategoryRecord>(); 
    } 
} 

public class MaterialPart : ContentPart<MaterialPartRecord> { 
    public IEnumerable<CategoryPartRecord> Categories { 
     get { return Record.Categories.Select(cmcr => cmcr.CategoryPartRecord); } 
    } 
} 

CategoryPartRecord

public class CategoryPartRecord : ContentPartRecord { 
    ... 
} 

public class CategoryPart : ContentPart<CategoryPartRecord> { 
    ... 
} 

관련 기록 : 이제 내가 필요

public class ContentMaterialCategoryRecord { 
    public virtual int Id { get; set; } 
    public virtual MaterialPartRecord MaterialPartRecord { get; set; }   
    public virtual CategoryPartRecord CategoryPartRecord { get; set; }   

} 

특정 카테고리에 연결된 MaterialItems을 선택하십시오. 지금까지 나는 그들을 추출하는이 방법을 가지고있다. 그것은 작동하지만 나는 이것이 올바른 방법임을 확신하지 않습니다.

public IEnumerable<MaterialPart> GetMaterialsByCategory(int catId) { 

    var cs = new CategoriesService(_oServices); 

    CategoryPartRecord cat = cs.GetItem(catId).Record; 

    return _oServices.ContentManager 
      .Query(VersionOptions.Latest, _contentType) 
      .Join<CommonPartRecord>() 
      .OrderByDescending(cpr => cpr.PublishedUtc); 
      .List() 
      .Where(ci => ci.IsPublished()) 
      .Select(ci => ci.As<MaterialPart>()) 
      .Where(mp => mp.Categories.Contains(cat));  // < ---- ?  
} 

그래서 내 질문은 : 우리는 단순히 필요한 CategoryPartRecord_Id 필드 값 inner join 관련된 기록 테이블에 필요로하는 최적의 SQL 쿼리를 생성에 필요한 범주에 대한 materials을 선택하는 올바른 방법이 무엇인지.

thaks!

+0

분류 체계를 사용하지 않는 이유를 설명 할 수 있습니까? –

+0

@BertrandLeRoy 빵 부스러기에 대해 이전 질문에서 이미 설명했습니다 :) 모든 작업에있어 만병 통치약이므로 분류법에 대해 항상 말합니다. – teran

+0

글쎄요, 제가 모든 질문에 누가 무엇을 말했는지 추적하지 않으면, 특히 그들에게 연결되어 있지 않다면 특히 용서해주십시오. 나는 명확한 유스 케이스가있을 때 항상 택 소노 미를 제기한다. 카테고리를 다시 구현하는 경우 * 정확히 어떤 분류를 위해 설계 되었습니까? 그럼 왜 그걸 사용하지 않니? –

답변

0

페어링 개체가있는 M : N의 경우 QueryOver 및 하위 쿼리를 사용할 수 있습니다. 가장 큰 장점은 우리가, 우리가

var session = ... // get curretn session 

CategoryPartRecord category = null; 
ContentMaterialCategoryRecord pair = null; 
MaterialPartRecord material = null; 

var subquery = QueryOver.Of<ContentMaterialCategoryRecord>(() => pair) 

    // now we will join Categories to be able to filter whatever property 
    .JoinQueryOver(() => pair.CategoryPartRecord,() => category) 

    // here is the filter 
    // there could be IN, >= <= ... 
    .Where(() => category.ID == 1) 
    // or 
    .WhereRestrictionOn(c => c.category.ID).IsIn(new[] {1, 2, 3}) 
    ... 

    // now we will return IDs of the Material we are interested in 
    .Select(x => pair.MaterialPartRecord.Id); 


// finally the clean query over the Materials... 
var listOfUsers = session.QueryOver<MaterialPartRecord>(() => material ) 
    .WithSubquery 
     .WhereProperty(() => material.Id) 
     .In(subquery) 
    // paging 
    .Take(10) 
    .Skip(10) 
    .List<MaterialPartRecord>(); 

그래서, 이것은 가장 효과적인 SQL 스크립트를 생성합니다() (생략) (취) 페이징에 사용할 수있는 재료 항목의 일반 세트를받을 것이 될 것이다 한 subselect, 그리고 재료 테이블에서 깨끗한 선택

참고 : 비슷한 것들은 LINQ도 함께 할 수 있습니다. 하지만 QueryOver NHibernate 가장 원시적 인 방식으로 말하고 싶습니다. 어쨌든, 카테고리별로 필터링 할 프린시 페 - 하위 쿼리와 자료를로드하는 기본 쿼리는 동일하게 유지됩니다. 오직 하나의 SQL Select 통화

+0

답변 해 주셔서 감사합니다! 나는 이것이 ** Orchard CMS **'ContentQueries' 물건 등이 없으면'NHibernate'를 사용하는 직접적인 방법이라고 이해합니다. – teran

+0

예. ;) 이것이 당신이 원하는 것 인 지 명확히하고 있는지, 미안, Orchard를 모른다. .. 그러나 NHibernate 길은 이것 일 것이다, 나는 말할 것이다) –