2012-06-12 5 views
3

검색 시스템을 조사해 본 결과 내 질문에 대한 대답을 찾지 못했지만이 질문은 유사하고 일부는 시작으로 사용하기까지했습니다. 벽돌 벽에 부딪쳤다.null이 될 수있는 부모 개체로 IL <Person> 정렬

나는 이미이 질문

I 객체가 다시 nHibernate 수에 의해 가져온 그런 다음

public class Person : IPerson, IComparable<Person>{ 

    // private properties 
    private int _id; 
    private string _name; 
    private Person _parent; 
    private IList<Person> _children; 
    private IList<Group> _groups; 

    // public properties 
    public virtual int id 
    { 
     get { return _id; } 
     set { _id = value; } 
    } 

    public virtual string name 
    { 
     get { return _name; } 
     set { _name= value; } 
    } 

    public virtual Person Parent 
    { 
     get { return _parent; } 
     set { _parent = value; } 
    } 

    public virtual IList<Person> Children 
    { 
     get { return _children; } 
     set { _children = value; } 
    } 

    public virtual IList<Group> Groups 
    { 
     get { return _groups; } 
     set { _groups = value; } 
    } 

    // constructor 
    public Person() {} 

    // this section I added after looking on SO 
    public virtual Int32 parentid 
    { 
     get { 
      if (_parent == null) 
      { 
      return _id; 
      } else { 
      return _parent.id; 
      } 
     } 
    } 

    public virtual Int32 CompareTo(Person obj) 
    { 
     if (this.id == obj.id) 
      return 0; 
     return this.parentid.CompareTo(obj.parentid); 
    } 
} 

을 다음과 같이 사람을 불렀다

을 확인했습니다 내 DAO의 목록을 가져 오는 방법 그룹 아래의 데이터베이스에있는 모든 개인 오브젝트들. 불행히도 입력 한 순서대로 다시 가져오고 부모 관계로 정렬하려고합니다. 내가 지금처럼이 answer에서 언급 한 바와 같이 정렬 할 때

i.e. (id,name,parent) 
person 1 (1,"Alice",null) 
person 2 (2,"Bob",1) 
person 3 (3,"Charlie",null) 
person 4 (4,"Dejgo",2) // child of a child 
person 5 (5,"Edgar", null) 
person 6 (6,"Florence", 3) 

는 :

class PeopleBLL : IPeopleBLL { 

    // spring properties 
    private IGroupsBLL _groupsBLL; 
    private IPeopleDao _peopleDao; 

    // public properties where spring sets up the links to the other dao and bll methods 
    public IGroupsBLL { 
     set{_groupsBLL = value;} 
    } 
    public IPeopleDao { 
     set{_peopleDao= value;} 
    } 

    // constructor 
    public PeopleBLL() 
    { 
    } 

    // method we are interested in 
    public IList<Person> GetAllInGroup(int groupID){ 
     //get the group object 
     Group groupObject = _groupsBLL.Get(groupID); 
     // get the people in the group 
     IList<Person> people = _peopleDao.GetAllInGroup(groupObject); 
     // do something here to sort the people 
     people.Sort(); 
     // return the list of people to aspx page 
     return people; 
    } 
} 

을 나는 형식

person 2 
person 1 
    person 6 
person 3 
person 5 
     person 4 

의 목록을 얻을 수 있지만 형식으로 원하는

person 1 
    person 2 
     person 4 
person 3 
    person 6 
person 5 

모든 ID eas?

편집 : 내가 사용하는 모든 여분의 기술에 의하여 문제를 혼동하고 싶지 않았기 때문에

나는이에서의 나머지 부분을 넣어하지 않았다하지만 난 질문을 받았다입니다. Spring.Net은 모든 객체를 연결하는 데 사용됩니다. 프론트 엔드 (asp.net 페이지), 비즈니스 계층 및 데이터베이스와 통신하는 Dao 계층이 있습니다. GetAllInGroup()을 업데이트하여 모든 작업을 보여 주었지만 관심있는 정렬 작업 만 수행했습니다. Dao는 nHibernate Criteria Query를 사용하여 그룹 아래의 모든 객체를 가져옵니다.

public IList<Person> getRegistrationsForDonor(Group groupObject) { 
     IList<Person> rv = CurrentSession.CreateCriteria(typeof(Person),"p") 
         .CreateCriteria("Groups","g") 
         .Add(Expression.Eq("g.id", groupObject.id)) 
         .List<Person>(); 
     return rv; 
    } 

그리고이 모든 것은 다음에있는 gridview에 의해 사용되는 오브젝트 데이터 소스

<asp:ObjectDataSource ID="ObjectDataSource1" OnObjectCreating="DataSource_ObjectCreating" runat="server" DataObjectTypeName="Domain.Person" TypeName="BusinessLayer.PersonBLL" DeleteMethod="delete" SelectMethod="GetAllInGroup" UpdateMethod="update"> 
    <SelectParameters> 
     <asp:ControlParameter ControlID="groupid" Type="Int32" DefaultValue="0" Name="groupID" /> 
    </SelectParameters> 
</asp:ObjectDataSource> 

에서 aspx 페이지에서 시작됩니다, 그래서 불행하게도 나는 전면에 BLL에서 정렬은 IList를 반환해야 단일 IList로 BLL 메소드에서 끝납니다.

편집 가정은 모든 부모가 최상위 수준에 null가됩니다 그 가정에서 올 수있는 내가 이해할 수 있지만 이론적으로있을 수 있음을하게되었습니다 죄송합니다 2

그룹의 유일한 어린이 그래서 객체의 어느 것도 null의 부모를 가지지 않습니다. 예를 들어 다음은 유효한 그룹입니다.나는 불행하게도이 모든 그래서 내가 여기에 응답해야합니다 코멘트에서 추측 할 수없는

person 2 
    person 4 
person 6 

편집 3

을 반환 희망

person 2 (2,"Bob",1) 
person 4 (4,"Dejgo",2) // child of a child 
person 6 (6,"Florence", 3) 

.

17시 30 분에 @ jon-senchyna 대답을 시도해 보니 확실히 가까워지고 있습니다. 일부 라이브 데이터에서이 작업을 시도했지만 거의 거기에 있습니다.하지만 이전에 오는 어린이들과 문제가있는 것 같습니다. 그룹의 부모. 48 명의 사람들이있는 그룹 1의 다음 예를 들자면 관심있는 사람들을 강조하겠습니다.

(789, "person 1", null) 
(822, "Person 34", null) 
(825, "Person 37", 789) 
(3060, "Person 47", 822) 
(3061, "Person 48", 825) 

이것은 그들이 데이터베이스에서 반환되는 순서는 있지만,이 종류를 넣을 때 그들은

Person 48 - id: 3061 
Person 37 - id: 825 
Person 1 - id: 789 
Person 47 - id: 3060 
Person 34 - id: 822 

그래서 아이들이 부모 옆에 순서대로하지만 역에 주문할 때, 내가 어디에서 주문하고 싶은지

Person 1 - id: 789 
Person 37 - id: 825 
Person 48 - id: 3061 
Person 34 - id: 822 
Person 47 - id: 3060 
+0

나머지 코드도 게시하여 코드에서 수행중인 작업을 명확하게 알 수 있습니까? – MMK

+0

손을 떼지 않으면 클래스가 부모 자식 관계를 식별하도록 매핑되었는지 확인합니다. 그렇다면 나는 'var q = = p from session.Query 여기서 p.parent == null by p.name'명령을 사용합니다. 그런 다음 NHibernate가 나머지를하도록하십시오. 이름이나 다른 것을 사용하기 위해 CompareTo를 오버라이드 (override)하는 것은 나쁜 생각이 아닙니다. – cloggins

+0

그냥 임의의 주석으로'_parent'를 선언 한 후에 세미콜론이 누락되었습니다.'_children'리스트는'person'이 아닌'Person' 유형이어야합니다. 나는 편집을 시도했지만, 그래서 내가 적어도 6자를 chaneg하지 않았다고 불평했다 ... –

답변

2

CompareTo를 통해이 작업을 수행하려는 경우 상위 트리 비교를 처리하는 데 더 많은 comlpex 논리가 필요할 수 있습니다. 다음은 가능한 솔루션입니다 :

public virtual Int32 CompareTo(Person person2) 
{ 
    Stack<Person> parents1 = GetParents(this); 
    Stack<Person> parents2 = GetParents(person2); 
    foreach (Person parent1 in parents1) 
    { 
     Person parent2 = parents2.Pop(); 
     // These two persons have the same parent tree: 
     // Compare their ids 
     if (parent1 == null && parent2 == null) 
     { 
      return 0; 
     } 
     // 'this' person's parent tree is contained in person2's: 
     // 'this' must be a parent of person2 
     else if (parent1 == null) 
     { 
      return -1; 
     } 
     // 'this' person's parent tree contains person2's: 
     // 'this' must be a child of person2 
     else if (parent2 == null) 
     { 
      return 1; 
     } 
     // So far, both parent trees are the same size 
     // Compare the ids of each parent. 
     // If they are the same, go down another level. 
     else 
     { 
      int comparison = parent1.id.CompareTo(parent2.id); 
      if (comparison != 0) 
      { 
       return comparison; 
      } 
     } 
    } 
    // We should never get here anymore, but if we do, 
    // these are the same Person 
    return 0; 
} 

public static Stack<Person> GetParents(Person p) 
{ 
    Stack<Person> parents = new Stack<Person>(); 
    // Add a null so that we don't have to check 
    // if the stack is empty before popping. 
    parents.Push(null); 
    Person parent = p; 
    // Recurse through tree to root 
    while (parent != null) 
    { 
     parents.Push(parent); 
     parent = parent.Parent; 
    } 
    return parents; 
} 

업데이트 : 두 부모 - 스택 이제 비교 로직을 좀 더 쉽게, 원래 사람이 포함되어 있습니다.

+0

이제는 첫 번째 단계에서 올바른 순서로 진행되었지만 여전히 4 세 (4 세, "Dejgo", 2 세)의 자녀가 마지막 항목이므로 여러 항목을 수용하기 위해 추가해야 할 사항이 있습니까? 레벨 구조. – kamui

+0

여러 레벨의 중첩을 처리하기 위해 내 대답이 업데이트되었습니다. 불행히도, 지금은 많은 복잡한 mroe지만, GetRoot 및 GetParents 같은 추가 기능은 정렬 이외의 다른 것들에 유용 할 수 있습니다. –

+0

코드를 조금 더 다시 실행 한 후에, 나는 약간의 복잡성을 제거 할 수있었습니다. 줄의 대부분은 단지 코멘트 일뿐입니다. 전반적으로 두 Person 객체의 부모 트리를 비교 한 다음 동일한 부모 트리가있는 경우 Person 객체 자체를 비교해야합니다. –

0

모든 사람을 불러 들이지 않아도됩니다. 부모가없는 사람 만로드하면 1, 3 및 5가 검색됩니다. 그리고 Children 속성을 사용하여 2, 4 및 6에 액세스 할 수 있습니다. hierachy가없는 순서대로 6 개의 목록을 얻으려면 3 개의 루트 노드를 반복적으로 검색하여 최종 목록을 만들 수 있습니다.

+0

또는 왕복을 피하려면 데이터베이스에서 모두로드 한 다음 말한대로 수행하십시오. 부모가없는 엔티티 만 반환하는 linq 쿼리의 경우 –

+0

[편집자]는 [사람]으로 [ Group]가 반환되면 루트 요소에 부모가 null이된다는 보장이 없습니다. – kamui

+0

좋아요, 그게 내 고심을 비웃는 것입니다. – Franky