【问题标题】:More elegant way to group DataTable data in structs in C# (using Linq?)在 C# 中对结构中的 DataTable 数据进行分组的更优雅的方法(使用 Linq?)
【发布时间】:2018-01-19 07:43:12
【问题描述】:

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

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

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

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

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

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

这又要存储在一个组结构中

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()));

我看到我的问题与这篇文章Group by in LINQ 密切相关,我想我可以先将我的数据表转换为列表,然后使用规定的方法。但理想情况下,我想绕过先转换为列表的步骤,直接对DataTable进行操作。

【问题讨论】:

    标签: c# linq datatable


    【解决方案1】:

    虽然我强烈建议从 DataTable 切换到使用大多数现代应用程序所做的模型(请参阅下面的参考资料),但 Microsoft 在 System.Data.DataTableExtensions 中提供了一个 AsEnumerable() 扩展方法,这就是您在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 query on a DataTable

    在您决定在 2020 年代使用 DataTable 之前,您应该阅读几篇文章(请记住,它已有近 20 年的历史,并且不是类型安全的):

    【讨论】:

    • 嗨。好,谢谢。我没有更新“模型”,但我会谷歌它:)
    • 你为什么说“强烈建议从 DataTable 切换到使用模型,就像大多数现代应用程序一样”你能扩展一下吗?
    • @Seabizkit - DataTable 就内存和性能而言不是很有效。虽然它没有被弃用,但它从 .NET 1.1 开始就存在了。对于性能不如易用性那么重要的一次性任务,它仍然很有用,但使用POCO 对象模型是在一线应用程序中处理数据的首选方式。
    • @NightOwl888 嗨,你能不能给我一些支持你的陈述的东西,关于内存和性能。
    • @NightOwl888 我很欣赏这次更新,但我已经阅读了这些内容,并且很多其他内容,我认为更重要的是你如何使用它,或者你使用它的什么因为,与其说它在记忆力或性能方面更好,这绝对不是真的,或者从我的阅读和理解来看……这取决于你试图做什么。我只是想我会指出这一点,因为我在数据表上看到了很多“仇恨”,但是在不了解赞成和反对的情况下,这实际上取决于您要做什么。示例...编写一个可以环绕未知列类型的类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多