我需要能够按特定顺序订购帐户列表。他们都有一个父级/子女关系。
因此,数据看起来像这样:
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首先按字母顺序排列为NULL ParentID,然后按字母顺序排列该父节点的任何子帐户。只是添加了子帐户中的“破折号”以获得视觉效果,因此请不要担心。
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;
}
答案 0 :(得分: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
答案 1 :(得分:0)
重写了它。我们无法保持按触发器维护的正确排序顺序,因此您必须做一些小技巧。我不确定这是否能直接用于Linq2Sql,但由于您需要所有记录,您可以将它们全部拉入List<Account>
,然后在客户端对该列表进行排序。
我们将按以下顺序排序:
null
(将来自同一父母的所有项目分组在一起),则为父OR的名称或我们自己的名称这是一个适用于我的符合您的架构的对象列表的查询:
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
};
}