在C#中使用结构将DataTable数据分组的更优雅的方法(使用Linq?) [英] More elegant way to group DataTable data in structs in C# (using Linq?)

查看:1193
本文介绍了在C#中使用结构将DataTable数据分组的更优雅的方法(使用Linq?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在数据库表中存储了几组数据,我想将它们转换成一个组结构列表,每个组包含数据数组.

I have groups of data stored in a database table that I want to transform into a list of group-struct, each containing arrays of data.

我可以使用相当长的方法来做到这一点.我想知道是否有更紧凑的方法来实现这一目标?我怀疑Linq应该适合这种操作,但我真的不知道如何开始.

I am able to do this using a rather long method. I was wondering if there is a more compact way of achieving this? I suspect Linq is supposed to be perfect for this kind of operation but I really don't know how to start.

以下示例说明了我当前正在做的事情.我的真实数据更复杂.

The following example illustrates what I am currently doing. My real data is more complex.

数据将存储在这样的结构中

The data is to be stored in a struct like this

public struct GroupData
{
    private string aString;
    private int anInt;

    public GroupData(string aString, int anInt)
    {
        this.aString = aString;
        this.anInt = anInt;
    }
}

再次将其存储在Group结构中

Which again is to be stored in a Group-struct

public struct Group
{
    private string groupId;
    private GroupData[] groupData;

    public Group(string groupId, GroupData[] groupData)
    {
       this.groupId = groupId;
       this.groupData = groupData;
    }
}

我目前正在这样做

//Create some dummy data
DataTable table = new DataTable();
table.Columns.Add("GROUP_ID", typeof(string));
table.Columns.Add("A_STRING", typeof(string));
table.Columns.Add("AN_INT", typeof(int));

table.Rows.Add("A", "this_is_A2", 7);
table.Rows.Add("A", "this_is_A2", 4);
table.Rows.Add("B", "this_is_B1", 3);
table.Rows.Add("C", "this_is_C1", 1);
table.Rows.Add("D", "this_is_D1", 3);
table.Rows.Add("D", "this_is_D2", 2);

//Create list of groups with arrays of groupdata
string theString, theGroupId;
int theInt;
List<Group> theGroups = new List<Group>();
List<GroupData> groupDataList;
Dictionary<string, List<GroupData>> groupDataDict = new Dictionary<string, List<GroupData>>();

//Read all rows and convert to structs
for (int i = 0; i < table.Rows.Count; i++)
{
    theGroupId = (string)table.Rows[i]["GROUP_ID"];
    theString = (string)table.Rows[i]["A_STRING"];
    theInt = (int)table.Rows[i]["AN_INT"];

    //Collect all GroupData into their respective Groups
    if (!groupDataDict.TryGetValue(theGroupId, out groupDataList))
    {
        groupDataList = new List<GroupData>();
        groupDataDict.Add(theGroupId, groupDataList);
    }
    groupDataList.Add(new GroupData(theString, theInt));
}

//Insert each group into the list
foreach (KeyValuePair<string, List<GroupData>> kv in groupDataDict)
    theGroups.Add(new Group(kv.Key, kv.Value.ToArray()));

我发现我的问题与这篇帖子在LINQ中分组依据密切相关,我想我可以先将数据表转换为列表,然后再使用规定的方法.但是理想情况下,我希望绕过首先转换为列表并直接在DataTable上进行操作的步骤.

I see that my question is closely related to this post Group by in LINQ and I guess I could first transform my datatable to a list, and then use the prescribed method. But Ideally I would like to bypass the step of first transforming to a list and operate directly on the DataTable.

推荐答案

尽管我强烈建议像大多数现代应用程序一样,从DataTable切换到使用模型(请参阅下面的参考资料),但是Microsoft提供了AsEnumerable()扩展方法在 System.Data.DataTableExtensions 就是在DataTable上使用LINQ所需要的.

While I would highly recommend switching from DataTable to using models as most modern applications do (see references below), Microsoft has provided an AsEnumerable() extension method in System.Data.DataTableExtensions that is all you need to use LINQ on a DataTable.

//Create some dummy data
DataTable table = new DataTable();
table.Columns.Add("GROUP_ID", typeof(string));
table.Columns.Add("A_STRING", typeof(string));
table.Columns.Add("AN_INT", typeof(int));

table.Rows.Add("A", "this_is_A2", 7);
table.Rows.Add("A", "this_is_A2", 4);
table.Rows.Add("B", "this_is_B1", 3);
table.Rows.Add("C", "this_is_C1", 1);
table.Rows.Add("D", "this_is_D1", 3);
table.Rows.Add("D", "this_is_D2", 2);

var groups = (from dt in table.AsEnumerable()
              group dt by dt.Field<string>("GROUP_ID") into g
              select new { 
                  GroupID = g.Key, 
                  GroupData = g.Select(i => i.Field<int>("AN_INT")) }
              ).ToList();

参考:对数据表的LINQ查询

在决定在2020年代使用DataTable之前,您应该阅读一些文章(请记住,它已经存在了将近20年,并且不是类型安全的):

A few articles you should read before you decide to use DataTable in the 2020's (keep in mind it is nearly two decades old and is not type safe):

  • Reasons to Move from DataTables to Generic Collections
  • What are the advantages of using POCOs over DataTables?

这篇关于在C#中使用结构将DataTable数据分组的更优雅的方法(使用Linq?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆