首页 > 解决方案 > 从 SQL 查询(存储过程)映射到 C# 类结构

问题描述

我有一个存储过程,它以以下格式返回数据:

public class Sp_Class
{
    public int ItemId { get; set; }

    public int ParentID { get; set; }
}

它将返回以下数据:

ItemId-ParentID

1 - 空

2 - 1

3 - 1

4 - 2

5 - 2

6 - 2

7 - 3

8 - 3

9 - 3

我现在想将它组织成以下递归类结构:

public class MappedStructure
{
    public int ItemId { get; set; }

    public List<MappedStructure> Children { get; set; }
}

这会将数据转换为以下格式:

    4
2   5
    6       

1

    7
3   8
    9

我知道我可以编写一个函数来执行此操作,但我觉得应该已经有工具可以执行此操作 - 例如,项目的其余部分使用已经执行此操作的实体框架。我相信这就是 ORM 的作用?

请注意,对于这个特定的查询,我不能使用实体,但这超出了本次讨论的范围。

标签: c#sqlorm

解决方案


这是一个关于如何使用 LINQ 执行此操作的示例。首先是一个示例数据表。我假设顶级项目的父 ID 为 Null。

var dataTable = new DataTable();
// Call Sp and fill data in DataTale

表示每项数据的类:

class Item {

  public Int32 ItemId { get; set; }

  public String Name { get; set; }

  public IEnumerable<Item> Children { get; set; }

}

获取特定项的子项的函数:

IEnumerable<DataRow> GetChildren(DataTable dataTable, Int32 parentId) {
  return dataTable
    .Rows
    .Cast<DataRow>()
    .Where(row => row.Field<Int32>("ParentID") == parentId);
}

创建包含子集合的项目的函数。此函数将向下递归层次结构:

Item CreateItem(DataTable dataTable, DataRow row) {
  var id = row.Field<Int32>("ItemId");
  var name = row.Field<String>("Name");
  var children = GetChildren(dataTable, id)
    .Select(r => CreateItem(dataTable, r))
    .ToList();
  return new Item { ItemId = id, Name = name, Children = children };
}

获取顶级项目行的函数:

IEnumerable<DataRow> GetTopLevelRows(DataTable dataTable) {
  return dataTable
    .Rows
    .Cast<DataRow>()
    .Where(row => row.Field<Int32>("ParentID") == null);
}

把它们放在一起:

var items = GetTopLevelRows(dataTable)
  .Select(row => CreateItem(dataTable, row))
  .ToList();

推荐阅读