Ran*_*dom 20 c# linq entity-framework hierarchy
我目前正试图找出一种用LINQ和C#对我的元素进行排序的好方法,但我有点没有这样做.
对于这个问题,我们假设您有以下表格
---TempTable
ID (int)
ParentID (int)
Name (varchar)
SortOrder (int)
Run Code Online (Sandbox Code Playgroud)
ID和ParentID彼此相关,并给我一个自我分层的数据结构.根元素在ID字段中为空.SortOrder只是整个表的一部分,并且基于ParentID,因此共享相同ParentID的元素中包含1,2,3.
让我们进一步假设以下数据:
ID = 1
ParentID = null
Name = Test 1
SortOrder = 1
ID = 2
ParentID = 1
Name = Test 2
SortOrder = 1
ID = 3
ParentID = 1
Name = Test 3
SortOrder = 2
ID = 4
ParentID = 2
Name = Test 4
SortOrder = 1
Run Code Online (Sandbox Code Playgroud)
我想要的平面列表应该具有以下顺序:
Test 1 //root element with sort order 1 = very top
Test 2 //child element of root with sort order 1
Test 4 //child element of test 2 with sort order 1
Test 3 //child element of root with sort order 2
Run Code Online (Sandbox Code Playgroud)
此外,我喜欢获取对象本身,而不仅仅获取一部分信息投入使用select new ...
这是我失败的尝试之一:
from x in EntityModel.TempTables //DbSet<TempTable> by EntityFramework - which already holds all elements
orderby x.SortOrder
from y in x.TempTableChildren //Navigation Property by EntityFramework
orderby y.SortOrder
select y
Run Code Online (Sandbox Code Playgroud)
在此先感谢您的帮助.
编辑:
具有ParentID的订单可能是有用的,对于给定的TestData,因为ID,ParentID处于完美的顺序但是在真实的实时应用程序中不是这样的,因为它的数据驱动,有人可以删除条目创建一个新条目并将其放入在父母的某些顺序,你会有类似的东西:
ID = 193475037
ParentID = 2
Name = Test 192375937
SortOrder = 25
Run Code Online (Sandbox Code Playgroud)
现在在应用程序中可以移动这个,ParentID和SortOrder会随机变化为:
ID = 193475037
ParentID = 456798424
Name = Test 192375937
SortOrder = 4
Run Code Online (Sandbox Code Playgroud)
为了解释这里的问题是一些代码 - 如果没有1个漂亮的Linq Query我会怎么做但是有2个和一些yield return:
public class LinqTestDemo
{
Random rand = new Random();
List<TempTable> list = new List<TempTable>();
public List<TempTable> GetFlatData()
{
list = GetTestData();
var rootElement = (from x in list
where x.ParentID == null
orderby x.SortOrder
select x).ToList();
var flatList = OrderChilds(rootElement).ToList();
foreach (var tempTable in flatList)
{
Console.WriteLine(string.Format("ID = {0} - ParentID = {1} - Name = {2} - SortOrder = {3}", tempTable.ID, tempTable.ParentID, tempTable.Name, tempTable.SortOrder));
}
return flatList;
}
private IEnumerable<TempTable> OrderChilds(List<TempTable> enumerable)
{
foreach (var tempTable in enumerable)
{
yield return tempTable;
TempTable table = tempTable;
var childs = OrderChilds((from x in list
where x.ParentID == table.ID
orderby x.SortOrder
select x).ToList());
foreach (var child in childs)
{
yield return child;
}
}
}
public List<TempTable> GetTestData()
{
var returnValue = new List<TempTable>();
for (int i = 0; i < 50; i++)
{
var tempTable = new TempTable();
tempTable.ID = i;
if (i == 0)
tempTable.ParentID = null;
else
tempTable.ParentID = rand.Next(0, i);
var maxSortOrder = (from x in returnValue
where x.ParentID == tempTable.ParentID
select (int?)x.SortOrder).Max();
if (maxSortOrder.HasValue)
tempTable.SortOrder = maxSortOrder.Value + 1;
else
tempTable.SortOrder = 1;
tempTable.Name = string.Format("Test {0:00}", i);
returnValue.Add(tempTable);
}
return returnValue;
}
public class TempTable
{
public int ID { get; set; }
public int? ParentID { get; set; }
public string Name { get; set; }
public int SortOrder { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
@Browth-First vs Depth-First Traversal:经过一些阅读后,我会说我想要的结果将是Depth-First Traversal,其中同一级别深度的元素应该由属性SortOrder排序.
Aka*_*ava 14
public lEnumerable<TempTable> GetList( int? parentID = null){
foreach ( var item in Context.TempTables
.Where( x => x.ParentID == parentID )
.OrderBy( x=> x.SortOrder)
.ToList() {
yield return item;
foreach( var child in GetList( item.ID))
{
yield return child;
}
}
}
var sortedList = GetList();
Run Code Online (Sandbox Code Playgroud)
它类似于您的方法,但它更小和递归.适用于许多深度级别.我更喜欢调用ToList,因为它会在查询下一个查询之前关闭resultset.
到目前为止,在单个查询中无法执行此操作.
请求单个查询
实体框架将自动填充所有孩子.
public IEnumerable<TempTable> PrepareList(IEnumerable<TempTable> list){
list = list.OrderBy( x=> x.SortOrder);
foreach(var item in list){
yield return item;
foreach(var child in PrepareList(item.ChildTempTables)){
yield return child;
}
}
}
// since EF will automatically fill each children on fetch
// all we need is just a top level nodes
// which we will pass to PrepareList method
var list = Context.TempTables.ToList().Where(x=> x.ParentID == null);
var sortedList = PrepareList(list).ToList();
// it is good to create list at the end if you are going to
// iterate it many times and logic will not change.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3808 次 |
| 最近记录: |