Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何更改DataTable结构,使列值位于多列中?_C#_Linq_Collections_Datatable_Transpose - Fatal编程技术网

C# 如何更改DataTable结构,使列值位于多列中?

C# 如何更改DataTable结构,使列值位于多列中?,c#,linq,collections,datatable,transpose,C#,Linq,Collections,Datatable,Transpose,如果我有一个这样结构的数据表: emp_num name status session_id 22 john 0 4 22 john 0 5 34 moh 1 3 35 Ran 0 3 35 Ran 0 4 emp_num name status session_id1 session_id2 session_id3

如果我有一个这样结构的数据表:

emp_num name  status  session_id

  22    john     0       4

  22    john     0       5

  34    moh      1       3

  35    Ran      0       3

  35    Ran      0       4
emp_num name  status  session_id1  session_id2  session_id3  session_id4 session_id5 

  22    john     0       0             0               0            1          1

  34    moh      1       0             0               1            0          0   

  35    Ran      0       0             0               1            1          0

如何将其转换为datatable,如下所示:

emp_num name  status  session_id

  22    john     0       4

  22    john     0       5

  34    moh      1       3

  35    Ran      0       3

  35    Ran      0       4
emp_num name  status  session_id1  session_id2  session_id3  session_id4 session_id5 

  22    john     0       0             0               0            1          1

  34    moh      1       0             0               1            0          0   

  35    Ran      0       0             0               1            1          0

我尝试创建带有循环的自定义数据表,但它不是通用的,我想要一些通用的数据表,因此如果我添加更多列或增加会话数,我不会得到超出范围的异常

using System.Data;
public static class DataTableExtensionMethods
{
    public static DataTable TransposeIntegerColumnIntoColumns(this DataTable dt, int indexColumnToEstablishDuplicateRows, int integerColumnIdToTranspose, string transposedColumnName)
    {
        //Protection if the column to transpose is not an integer or doesn't exist
        if (integerColumnIdToTranspose >= dt.Columns.Count) return null;
        var columnDataType = dt.Columns[integerColumnIdToTranspose].DataType;
        if (columnDataType != typeof(int)) return null;

        //Get max sessions number
        int maxColumnNumber = 0;
        foreach (DataRow dr in dt.Rows)
        {
            int? number = dr.Field<int?>(integerColumnIdToTranspose);
            if (number != null)
            {
                maxColumnNumber = Math.Max(maxColumnNumber, (int)number);
            }
        }

        //Protection if there are zero rows or the maxColumnNumber is 0
        if (dt.Rows.Count == 0 || maxColumnNumber == 0) return null;

        //Make a copy of the table so we can remove duplicate rows and add the transposed columns
        DataTable result = dt.Copy();

        //Add columns to store the session_ids
        for (int i = 1; i <= maxColumnNumber; i++)
        {
            DataColumn dc = new DataColumn(transposedColumnName + i.ToString(), typeof(int));
            dc.DefaultValue = 0;
            //Possibly make an overloaded method that supports inserting columns
            result.Columns.Add(dc);
        }

        //Remove rows with duplicated employees
        for (int i = 0; i < result.Rows.Count; i++)
        {
            int duplicateRow = GetRowIndexById(result, indexColumnToEstablishDuplicateRows, result.Rows[i][indexColumnToEstablishDuplicateRows].ToString(), i + 1);
            if (duplicateRow > -1)
            {
                result.Rows.RemoveAt(duplicateRow);
            }
        }

        //Populate the transposed columns with values in the integer Column To Transpose
        foreach (DataRow dr in dt.Rows)
        {
            int? sessionNumber = dr.Field<int?>(integerColumnIdToTranspose);
            if (sessionNumber == null) continue;
            int rowIndex = GetRowIndexById(result, indexColumnToEstablishDuplicateRows, dr[indexColumnToEstablishDuplicateRows].ToString(), 0);

            result.Rows[rowIndex][transposedColumnName + sessionNumber.ToString()] = 1; //or +=1 if you want to increment the number
        }

        //Remove the integerColumnIdToTranspose (again overload this method if you want to keep this column)
        result.Columns.RemoveAt(integerColumnIdToTranspose);

        return result;
    }

   //Net 4 implementation with optional parameter
   //private static int GetRowIndexById(DataTable dt, int indexColumnToEstablishDuplicateRows, string id, int startLookAtRow = 0)
    private static int GetRowIndexById(DataTable dt, int indexColumnToEstablishDuplicateRows, string id, int startLookAtRow)
    {
        for (int i = startLookAtRow; i < dt.Rows.Count; i++)
        {
            if (dt.Rows[i][indexColumnToEstablishDuplicateRows].ToString() == id) return i;
        }
        return -1;
    }
}
结果是:


我认为你的方法有根本性的问题。如果员工和会话之间存在一对多关系,则需要有两个表。一个表用于员工,其中每个员工有一行,另一个表用于会话,其中每个会话有一行。每个会话记录都应该有一个“emp_num”将其链接回员工。@Keith:是的,有两个表,我在这两个表之间建立了一个连接,并在datatable中设置结果。现在,我想要一个具有以下结构的报告
emp\u num name status session\u id1 session\u id2 session\u id3…
列的数量取决于session\u id valueOk,将DataTable扩展方法类中的代码复制/粘贴到您的项目中,我使其与.Net 3.5兼容:)我确实测试了这段代码。奇怪的添加对null值的检查是好的,尽管我不确定这行代码如何引发异常:
int?sessionNumber=dr.Field(integercolumnidtottranspose)
在添加列session\u id0之前。感谢您的提示。在我的代码中,请参见如何为添加以1:
开头的列(int i=1;i不,我没有更改代码,但有时我会有这样的数据
34 Moh 0 null
因为数据表结果来自
outer join
对所有编辑表示歉意,我已经用null会话测试了此方法,它是有效的。如果遇到任何其他问题,请告诉我。干杯