C# 在具有多表的Linq查询中使用递归层次树结构并返回一些Json值
我有一个复杂的层次结构,我使用了这个方法,它返回给我一个包含父节点、子节点和深度的树结构。所以这没关系,但我需要从数据库的ScoreItem表中计算总分。正如我在下面用t-sql编写的这个简单的计算方法一样C# 在具有多表的Linq查询中使用递归层次树结构并返回一些Json值,c#,json,linq,recursion,C#,Json,Linq,Recursion,我有一个复杂的层次结构,我使用了这个方法,它返回给我一个包含父节点、子节点和深度的树结构。所以这没关系,但我需要从数据库的ScoreItem表中计算总分。正如我在下面用t-sql编写的这个简单的计算方法一样 Begin Select sp.Name, u.FirstName + ' ' + u.LastName as NameAndSurname, rgc.Name as ScoreCard, si.TotalPoint
Begin
Select
sp.Name,
u.FirstName + ' ' + u.LastName as NameAndSurname,
rgc.Name as ScoreCard,
si.TotalPoint
from Score s
inner join ScoreItem si on si.ScoreId = s.Id
inner join ProjectResearchGroup prg on si.ProjectResearchGroupId = prg.Id
inner join RgClone rgc on prg.RgCloneId = rgc.Id
inner join Salespoint sp on s.SalesPointId = sp.Id
inner join SalesHierarchySalesPoint shsp on sp.Id = shsp.SalesPointId
inner join SalesHierarchy sh on shsp.SalesHierarchyId = sh.Id
inner join [User] u on u.Id = sh.CompanyResponsibleId
where sh.Id in
(Select Id
from SalesHierarchy
where ParentId in
(Select Id
from SalesHierarchy
where ParentId in
(Select Id
from SalesHierarchy
where ParentId in
(Select Id
from SalesHierarchy
where CompanyId = 2
and ParentId is null))))
and si.IsValidForSalesPoint = 1
End
另外,这是我的后端代码,用于尝试从上述t-sql查询实现linq查询
IEnumerable<FlatData> _SalesHierarchy = db.SalesHierarchy
.Select(sh =>
new FlatData()
{
Id = sh.Id,
ParentId = sh.ParentId ?? 0,
Text = sh.Name
})
.ToList();
IEnumerable<DeepNodeData> nodes = _SalesHierarchy.RecursiveJoin(e => e.Id, e => e.ParentId,
(FlatData sh, int index, int depth, IEnumerable<DeepNodeData> children) =>
{
return new DeepNodeData
{
Id = sh.Id,
ParentId = sh.ParentId,
Text = sh.Text,
Children = children,
Depth = depth
};
如何使用其他linq查询实现层次查询,并返回高于Json格式的结果。如果您对此有任何建议和示例应用程序,请与我分享,看起来很不错,但我认为您不需要该代码的全部功能来实现您的目标。如果我正确理解您的问题,您需要从根到叶枚举所有节点列表,将每个列表转储到JSON对象中。为此,首先创建以下扩展方法:
public static class RecursiveExtensions
{
public static IEnumerable<TValue> SelfAndParents<TKey, TValue>(this TValue value, IDictionary<TKey, TValue> dictionary, Func<TValue, TKey> getParentKey)
{
HashSet<TValue> returned = new HashSet<TValue>();
do
{
yield return value;
if (!dictionary.TryGetValue(getParentKey(value), out value))
yield break;
if (returned.Contains(value))
throw new InvalidOperationException("Circular reference");
returned.Add(value);
}
while (true);
}
public static IEnumerable<List<TValue>> FlattenTree<TKey, TValue>(this IEnumerable<TValue> nodes, Func<TValue, TKey> getKey, Func<TValue, TKey> getParentKey)
{
var list = nodes.ToList(); // Don't iterate through the node list more than once.
var parentKeys = new HashSet<TKey>(list.Select(getParentKey)); // Built a set of parent keys.
var dict = list.ToDictionary(getKey); // Build a dictionary of key to value
var results = list
.Where(node => !parentKeys.Contains(getKey(node))) // Filter out non-leaf nodes
.Select(node => node.SelfAndParents(dict, getParentKey).Reverse().ToList()); // For each leaf return a list going from root to leaf.
return results;
}
}
这是你想要的吗?在这里,我利用Json.NET将字典序列化为Json对象的事实,动态创建“
levelI
”属性作为字典键。另外,由于您没有定义“val”
值,所以我没有将其包含在字典中。val的意思是,总分它来自DbContext上的ScoreItem,它必须显示最后一级的末尾@Ozkan-在FlatData上没有与ScoreItem
对应的内容。数据可以添加到那里吗?事实上,我必须加入Score、ScoreItem、Salespoint和SalesHierarchy来准备计算每个Salespoint的积分卡TotalPoint,例如,Alamut Kırtasiye,但谁是Alamut Kırtasiye,谁是其父母??因此,首先我必须得到与阿拉穆特K有关的层次结构。所以“1级”:“Anadolu SatışMerkezi”,“2级”:“Emrullahşelik”,“3级”:“Ahmetşşler”/“4级”:“阿拉穆特K”Val:“45.66”,Val显示了计算的最终全点,例如,请看这里,
public static class RecursiveExtensions
{
public static IEnumerable<TValue> SelfAndParents<TKey, TValue>(this TValue value, IDictionary<TKey, TValue> dictionary, Func<TValue, TKey> getParentKey)
{
HashSet<TValue> returned = new HashSet<TValue>();
do
{
yield return value;
if (!dictionary.TryGetValue(getParentKey(value), out value))
yield break;
if (returned.Contains(value))
throw new InvalidOperationException("Circular reference");
returned.Add(value);
}
while (true);
}
public static IEnumerable<List<TValue>> FlattenTree<TKey, TValue>(this IEnumerable<TValue> nodes, Func<TValue, TKey> getKey, Func<TValue, TKey> getParentKey)
{
var list = nodes.ToList(); // Don't iterate through the node list more than once.
var parentKeys = new HashSet<TKey>(list.Select(getParentKey)); // Built a set of parent keys.
var dict = list.ToDictionary(getKey); // Build a dictionary of key to value
var results = list
.Where(node => !parentKeys.Contains(getKey(node))) // Filter out non-leaf nodes
.Select(node => node.SelfAndParents(dict, getParentKey).Reverse().ToList()); // For each leaf return a list going from root to leaf.
return results;
}
}
public static class TestFlatten
{
public static IEnumerable<FlatData> GetFlatData()
{
// Get sample data for testing purposes.
var list = new List<FlatData>
{
new FlatData { Id = 1, ParentId = 0, Text = "Some Root Node" },
new FlatData { Id = 2, ParentId = 0, Text = "Anadolu Satış Merkezi" },
new FlatData { Id = 3, ParentId = 2, Text = "Emrullah Çelik" },
new FlatData { Id = 4, ParentId = 3, Text = "Ahmet İşler" },
new FlatData { Id = 5, ParentId = 4, Text = "Elpa Pazarlama Nazmi Appak" },
new FlatData { Id = 6, ParentId = 4, Text = "Elpa Pazarlama Nazmi Appak Redux" },
new FlatData { Id = 11, ParentId = 1, Text = "Some Child of Some Root Node" },
};
return list;
}
public static void Test()
{
var nodes = GetFlatData();
var flatNodes = nodes.FlattenTree(d => d.Id, d => d.ParentId);
var results = flatNodes.Select(
list => list
.Select((d, i) => new KeyValuePair<int, FlatData>(i, d))
.ToDictionary(pair => string.Format("level{0}", pair.Key + 1), pair => pair.Value.Text))
.ToList();
var json = JsonConvert.SerializeObject(new { data = results }, Formatting.Indented);
Debug.WriteLine(json);
}
}
{
"data": [
{
"level1": "Anadolu Satış Merkezi",
"level2": "Emrullah Çelik",
"level3": "Ahmet İşler",
"level4": "Elpa Pazarlama Nazmi Appak"
},
{
"level1": "Anadolu Satış Merkezi",
"level2": "Emrullah Çelik",
"level3": "Ahmet İşler",
"level4": "Elpa Pazarlama Nazmi Appak Redux"
},
{
"level1": "Some Root Node",
"level2": "Some Child of Some Root Node"
}
]
}