我最近需要对页面列表和导航菜单条目进行排序,它们相互关联。
每个 Navigation
都有一个 Page
属性。每个 Page
都有一个 Navigation
属性。它们是我数据库中的外键引用。
我有一个 Navigation
项目列表以及每个 Page
项目列表。问题在于,无论 Page
是否与 Navigation
相关联,它都存储在 Page
项的列表中。
我想生成一个排序的 Page
项目列表,如下所示:具有非空 Navigation
的项目按 Page.Navigation.Index< 排序
属性。具有空 Navigation
的项目按 Page.Title
属性排序,然后按 Page.ID
属性排序。
以下是我们目前所做的,大部分情况下都有效,但也有少数异常(exception)。 我遇到的问题是它不处理没有关联导航的页面的重复标题。
List<Page> page1 = db.Navigations.OrderBy(n => n.Index).Select(n => n.Page).ToList();
List<Page> page2 = db.Pages.Where(p => !db.Navigations.Contains(p.Navigation)).ToList();
model.Pages = page1.Concat(page2).ToList();
这是一些示例数据和预期结果
Pages Table (PageID, Title, Content)
0, "Home", "<html>This is a home page</html>"
3, "Some Page", "<html>This is some page.</html>"
2, "Some hidden page", "<html>This is some hidden page.</html>"
4, "Products", "<html>We've got products!</html>"
5, "aaaaa", "<html>This should be sorted to the top of pages with no nav</html>"
Navigations Table (PageID, Index)
0, 0
3, 2
4, 1
Output (PageID, Title, Content)
0, "Home", "<html>This is a home page</html>"
4, "Products", "<html>We've got products!</html>"
3, "Some Page", "<html>This is some page</html>"
5, "aaaaa", "<html>This should be sorted to the top of pages with no nav</html>"
2, "Some hidden page", "<html>This is some hidden page.</html"
我很好奇这是否有可能以更好看的方式以及在查询语法而不是过程语法中完成。
最佳答案
我猜这会解决问题:
model.Pages = db.Pages
.OrderBy(p=>p.Navigation != null ? p.Navigation.Index : Int32.MaxValue)
.ThenBy (p=>p.Title)
.ThenBy (p=>p.PageID)
.ToList();
或者如果你喜欢这种语法
var query = from p in db.Pages
orderby p.Navigation != null ? p.Navigation.Index : Int32.MaxValue,
p.Title,
p.PageID
select p;
model.Pages = query.ToList();
当 Navigation.Index 存在时,页面按 Navigation.Index 排序,没有 Navigation.Index 的页面将出现在这些页面之后(它们实际上将 Int32.MaxValue 作为 Navigation.Index)。因为没有 Navigation.Index 的那些现在有一个唯一值 (Int32.MaxValue),所以这些将再次按 Title 然后按 PageId 排序。
关于c# - 使用 LINQ 按多个表中的多个属性有条件地对元素进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10240658/