3

私は検索システムを調べてきましたが、私の問題に対する答えに出くわしませんでしたが、これらの質問は似ていて、それらのいくつかを使用してスタートを切ったのですが、レンガの壁にぶつかりました.

私はすでにこれらの質問をチェックアウトしました

次のように、Person という 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 のメソッド。残念ながら、入力された順序に戻ってしまうので、親子関係に分類したいと思います。

 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

何か案は?

編集:

使用されるすべての余分なテクノロジーによって質問を混乱させたくなかったので、これの残りを入れませんでしたが、尋ねられたので. Spring.Net を使用してすべてのオブジェクトをリンクします。3 層アーキテクチャのフロント エンド (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;
  }

そして、これはすべて、オブジェクト データソースの aspx ページで開始されます

 <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>

これは gridview によって使用されるため、残念ながら、並べ替えられた IList を BLL から BLL メソッドのフロント エンドに単一の IList として返す必要があります。

編集 2

申し訳ありませんが、すべての親が最上位で null になるという仮定が行われました。その仮定がどこから来るのかは理解できますが、理論的にはグループ内に子のみを含めることができるため、オブジェクトの親が null になることはありません。たとえば、次は有効なグループです。

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

戻ってくることを願っています

 person 2
    person 4
 person 6

編集 3

残念ながら、コメントでこれらすべてを推測することはできなかったので、ここで返信する必要があります。

17:30 に @jon-senchyna の回答を試してみたところ、確実に近づいています。これをいくつかのライブ データで試してみたところ、ほぼ完了しましたが、グループ内の親の前に子供が来るという問題が発生しているようです。 . 次の例のグループ 1 には 48 人がいます。関心のある人を強調します。

 (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
4

2 に答える 2

2

CompareTo を介してこれを行いたい場合は、親ツリーの比較を処理するために、さらに複雑なロジックが必要になる場合があります。以下は可能な解決策です:

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

更新:両方の親スタックに元の人物が含まれるようになり、比較ロジックが少し簡単になりました。

于 2012-06-12T13:10:44.343 に答える
0

考慮事項: すべての人をロードする必要はありません。親なしで人物のみをロードすると、1、3、および 5 が取得されます。また、Children プロパティを使用して 2、4、および 6 にアクセスできます。その順序で (階層なしで) 6 つすべてのリストを取得するには、3 つのルート ノードを再帰的に調べて、最終的なリストを作成します。

于 2012-06-12T12:45:19.287 に答える