繁体   English   中英

在 linq 中有没有一种方法可以使用列名 C# 在数据表中插入一行(来自字典)?

[英]Is there a way in linq wherin i can insert a row(from dictionary) in datatable using the list of column names c#?

我有一个List<Dictionary<string,string>>是这样的:
[0] key1 val,key2 val,key3 val
[1] key1 val,key2 val,key3 val
[2] key1 val,key2 val,key3 val

我有一个列名列表,其顺序与数据表中的列的顺序相同。 我只想从字典中过滤列表中的那些键,并以正确的顺序插入它。

我能够过滤要插入的所需键,但是如何在 linq 中以正确的顺序插入它。

var colList = new List<string>() { "key3", "key1"};
dict.ForEach(p => jsonDataTable.Rows.Add(p.Where(q=>colList.Contains(q.key)).Select(r => r.Value).ToArray()));

我不能这样做,因为列数会有所不同,而且当我们传递任何列名列表时,该方法必须工作:

foreach(var item in dict)
 jsonDatatable.Rows.Add(item[colList[0]], item[colList[1]]);

请提出一些方法。

LINQ 永远不会改变输入源。 您只能从中提取数据。

将问题分解为子问题

更改输入源的唯一方法是使用提取的数据来更新源。 确保在更新源之前您已经具体化了您的查询(= ToList() 等)

您可以将问题分解为子问题:

  • 按正确顺序将表转换为列序列
  • 将列序列转换为列名序列(仍按正确顺序排列)
  • 使用列名和字典来获取请求的数据。

通过将您的问题分成这些步骤,您可以为可重用性准备解决方案。 如果将来您将表更改为 DataGridView,或实体框架数据库中的表,或 CSV 文件,甚至 JSON,您可以重用后面的步骤。 如果将来您需要将列名用于其他用途,您仍然可以使用前面的步骤。

为了能够以类似 LINQ 的方式使用代码,我的建议是创建扩展方法。 如果您不熟悉扩展方法,请阅读扩展方法揭秘

您将更熟悉表的布局(System.Data.DataTable?Windows.Forms.DataGridView?Windows.Controls 中的 DataGrid?)和列,因此您必须自己创建第一个列。 在示例中,我使用了 MyTable 和 MyColumn; 将它们替换为您自己的 Table 和 Column 类。

public static IEnumerable<MyColumn> ToColumns(this MyTable)
{
     // TODO: return the columns of the table
}

public static IEnumerable<string> ToColumnNames(this IEnumerable<MyColumn> columns)
{
    return columns.Select(column => ...);
}

如果列名只是列的一个属性,我不会费心创建第二个过程。 然而,好消息是它隐藏了你从哪里得到名字。 因此,为了面向未来的变化,无论如何都可以创建该方法。

您说这些列已排序。 如果您希望能够使用ThenBy(...)考虑返回IOrderedEnumerable<MyColumn> 如果你不对排序结果进行排序,我不会打扰。

用法:

MyTable table = ...
IEnumerable<string> columnNames = table.ToColumns().ToColumnNames();

或者:

IEnumerable<string> columnNames = table.ToColumns()
    .Select(column => column.Name);

第三个子问题是有趣的。

加入和群组加入

在 LINQ 中,只要您有两个表并且想要使用一个表中元素的属性将它们与另一个表的属性匹配,请考虑使用 (Group-)Join。

如果您只希望第一个表中的项目与另一个表中的一个项目完全匹配,请使用Join :“使用他的地址获取客户”,“通过其供应商获取产品”。 “与其作者一起预订”

另一方面,如果您希望第一个表的一个项目与另一个表中的零个或多个项目匹配,请使用GroupJoin :“学校,每个人都有他们的学生”,“客户,每个人都有他们的订单”,“作者,每个人与他们的书”

有些人仍然用数据库术语来思考。 他们倾向于使用某种Left Outer Join来获取“学校与学生”。 这样做的缺点是,如果一个 School 有 2000 个学生,那么这个 School 的相同数据要传输 2000 次,每个学生传输一次。 GroupJoin只会传输 School 的数据一次,每个 Student 的数据也只会传输一次。

回到你的问题

在您的问题中:每个列名都是字典中一个项目的键。

你想用没有键的列名做什么? 如果要丢弃它们,请使用Join 如果您仍想使用字典中没有任何内容的列名,请使用GroupJoin

IEnumerable<string> columNames = ...
var result = columnNames.Join(myDictionary,

    columName => columName,                // from every columName take the columnName,
    dictionaryItem => dictionaryItem.Key,  // from every dictionary keyValuePair take the key

    // parameter resultSelector: from every columnName and its matching dictionary keyValuePair
    // make one new object:
    (columnName, keyValuePair) => new
    {
        // Select the properties that you want:
        Name = columnName,

        // take the whole dictionary value:
        Value =  keyValuePair.Value,

        // or select only the properties that you plan to use:
        Address = new
        {
            Street = keyValuePair.Street,
            City = keyValuePair.City,
            PostCode = keyValuePair.Value.PostCode
            ...
        },
    });

如果您更频繁地使用它:考虑为此创建一个扩展方法。

注意:未指定 Join 的结果顺序,因此您必须在 Order 后排序

用法:

Table myTable = ...
var result = myTable.ToColumns()
                    .Select(column => column.Name)
                    .Join(...)
                    .Sort(joinResult => joinResult.Name)
                    .ToList();

不是在 List<Dictionary<string, string>> 上过滤, colListcolList上过滤,以便您获得相同的顺序,并且仅当 colList 在List<Dictionary<string, string>>可用时

这是我的理解,如果您需要任何其他方式的结果,请发表评论。

var dictAllValues = dict.SelectMany(x => x.Select(y => y.Value)).ToList();
// Now you can filter the colList using the above values
var filteredList = colList.Where(x => dictAllValues.Contains(x));

// or you can directly add to final list as below
jsonDataTable.Rows.AddRange(colList.Where(x => dictAllValues.Contains(x)).ToList());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM