0

我需要能够以特定顺序订购帐户列表。它们都具有一级父/子关系。

所以,数据看起来像这样:

AccountID    AccountName    ParentID
1            Blue           NULL
2            Red            NULL
3            Green          NULL
4            Yellow         3
5            Orange         2
6            Purple         1
7            Voilet         1
8            Gold           2

etc...

我需要填充一个下拉列表,如下所示(如下),该列表由 AccountID 排序,其父 ID 为 NULL,首先按字母顺序排列,然后任何子帐户都按字母顺序排列。儿童帐户上的“破折号”只是为了视觉效果而添加的,所以不用担心。

Blue
- Purple
- Voilet
Green
- Yellow
Red
- Gold
- Orange

这是我之前使用的代码(如下),但是在大约 30 个帐户之后它开始给我这个错误。

您的 SQL 语句的某些部分嵌套得太深。重写查询或将其分解为更小的查询。

Public Function GetAllActiveAccountsForAccountSwitcher() As IEnumerable(Of Models.AccountDropDownListModel)
    Dim isFirst As Boolean = True
    Dim list As IQueryable(Of Models.AccountDropDownListModel) = Nothing

    Dim parentAccts As IQueryable(Of Account) = From a As Account In dc.Accounts _
            And a.ParentID Is Nothing _
            Order By a.AccountName

    For Each parentAcct In parentAccts

        Dim parent = From a In dc.Accounts Where a.AccountID = parentAcct.AccountID _
            Select New Models.AccountDropDownListModel _
            With { _
                .AccountID = a.AccountID,
                .AccountName = a.AccountName
            }
        If isFirst Then
            list = parent
            isFirst = False
        Else
            list = list.Union(parent)
        End If

        Dim child = From a As Account In dc.Accounts Where a.ParentID = parentAcct.AccountID _
           Select New Models.AccountDropDownListModel _
                With { _
                    .AccountID = a.AccountID,
                    .AccountName = "- " & a.AccountName
                }
        list = list.Union(child)

    Next

    Return list
End Function

C# 或 VB.NET 示例很好。我不知道,但它需要使用 linq-to-sql。存储过程不是我的情况的选择。

更新: 对于对 VB 过敏的人来说,这是我的原始代码的 c#...

public IEnumerable<Models.AccountDropDownListModel> GetAllActiveAccountsForAccountSwitcher()
{
    bool isFirst = true;
    IQueryable<Models.AccountDropDownListModel> list;

    IQueryable<Account> parentAccts = from a in dc.Accounts & a.ParentID == null orderby a.AccountName;


    foreach (void parentAcct_loopVariable in parentAccts) {
        parentAcct = parentAcct_loopVariable;
        var parent = from a in dc.Accountswhere a.AccountID == parentAcct.AccountID select new Models.AccountDropDownListModel {
            AccountID = a.AccountID,
            AccountName = a.AccountName
        };
        if (isFirst) {
            list = parent;
            isFirst = false;
        } else {
            list = list.Union(parent);
        }

        var child = from a in dc.Accountswhere a.ParentID == parentAcct.AccountID select new Models.AccountDropDownListModel {
            AccountID = a.AccountID,
            AccountName = "- " + a.AccountName
        };
        list = list.Union(child);

    }

    return list;
}
4

2 回答 2

1

RRrrrggg 我太笨了。事实证明这很简单。我只是在我的模型中添加了一个“SortName”字符串,然后按它排序。

Public Function GetAllActiveAccountsForAccountSwitcher() As IEnumerable(Of Models.AccountDropDownListModel)
    Dim parentAccts As IQueryable(Of Account) = From a As Account In dc.Accounts

    Return parentAccts.Select(Function(a) New Models.AccountDropDownListModel _
                With { _
                    .SortName = IIf(a.ParentID Is Nothing, a.AccountID, a.ParentID & "_Child"),
                    .AccountID = a.AccountID,
                    .AccountName = IIf(a.ParentID Is Nothing, a.AccountName, "- " & a.AccountName)
                }).OrderBy(Function(a) a.SortName).ThenBy(Function(a) a.AccountName)
End Function
于 2013-09-25T16:39:47.993 回答
0

重新写了。我们不能像我们应该的那样保持由触发器维护的正确排序顺序,所以你必须做一些小把戏。我不确定这是否会直接在 Linq2Sql 中工作,但由于您需要所有记录,您可以将它们全部拉入 aList<Account>中,然后在客户端对该列表进行排序。

我们将按以下顺序订购的东西:

  1. 父母的姓名或或我们自己的姓名 if null将来自一位父母的所有项目组合在一起
  2. 一行是父母的事实(将父母放在首位
  3. 名称(命令孩子,不影响父母

这是一个对与您的架构匹配的对象列表对我有用的查询:

var result = 
    from a in Accounts
    // Get one value that is the same for both a parent & a child.
    // Since we need to sort alphabetically, we use the
    // parent name.  We only have the ID (parentId), so we need to do
    // a lookup into the list to get the parent.Name.  If the parentId
    // is null, it means we ARE the parent, so we use our own name
    let sortingGroup = Accounts.Where(x => x.Id == a.ParentId)
                            .Select(x => x.Name)
                            .FirstOrDefault() ?? a.Name
    orderby
        sortingGroup,
        a.ParentId == null descending,
        a.Name
    select new
        {
            SortingGroup = sortingGroup,
            Id = a.Id,
            Name = a.Name,
            ParentId = a.ParentId
        };
    }
于 2013-09-25T15:39:42.003 回答