• DataTable的操作类


           本文主要提供了一个操作DataTable的类,DataTable的常用操作包括Join,Top,Select,Distinct等。

    View Code
    using System;
    using System.Collections.Generic;
    using System.Text;

    using System.Data;

    namespace Common.Data
    {
        /// <summary>
        
    /// This helper class provides some useful function for processing the in-memory DataTable.
        
    /// Reference:http://weblogs.sqlteam.com/davidm/archive/2004/01/20/748.aspx
        
    /// </summary>
        public static class DataTableHelper
        {
            public static DataTable Join(DataTable leftTable, DataTable rightTable, DataColumn[] leftKeyColumnArray, DataColumn[] rightKeyColumnArray, DataColumn[] leftResultColumnArray, DataColumn[] rightResultColumnArray, JoinType joinType, bool fillKeyColumn, string prefixForDuplicatedColumn)
            {
                DataTable result = new DataTable();

                // Use a DataSet to leverage DataRelation
                using (DataSet ds = new DataSet())
                {
                    {
                        DataTable left = leftTable.Copy();
                        left.TableName = "leftTable";
                        DataTable right = rightTable.Copy();
                        right.TableName = "rightTable";
                        ds.Tables.AddRange(new DataTable[] { left, right });
                    }

                    //Identify joining columns from the left table.
                    DataColumn[] parentcolumns = new DataColumn[leftKeyColumnArray.Length];

                    for (int i = 0; i < parentcolumns.Length; i++)
                    {
                        parentcolumns[i] = ds.Tables[0].Columns[leftKeyColumnArray[i].ColumnName];
                    }

                    //Identify joining columns from the right table.
                    DataColumn[] childcolumns = new DataColumn[rightKeyColumnArray.Length];
                    for (int i = 0; i < childcolumns.Length; i++)
                    {
                        childcolumns[i] = ds.Tables[1].Columns[rightKeyColumnArray[i].ColumnName];
                    }

                    DataRelation r = new DataRelation(string.Empty, parentcolumns, childcolumns, false);

                    ds.Relations.Add(r);

                    //Create columns for result table
                    foreach (DataColumn dc in leftResultColumnArray)
                    {
                        result.Columns.Add(dc.ColumnName, dc.DataType);
                    }

                    foreach (DataColumn dc in rightResultColumnArray)
                    {
                        if (!result.Columns.Contains(dc.ColumnName))
                        {
                            result.Columns.Add(dc.ColumnName, dc.DataType);
                        }
                        else
                        {
                            //The caller should make sure the prefix can make a unique column name.
                            result.Columns.Add(prefixForDuplicatedColumn + dc.ColumnName, dc.DataType);
                        }
                    }

                    result.BeginLoadData();
                    if (joinType == JoinType.InnerJoin)
                    {
                        foreach (DataRow leftRow in ds.Tables[0].Rows)
                        {
                            DataRow[] rightRows = leftRow.GetChildRows(r);
                            if (rightRows.Length > 0)
                            {
                                foreach (DataRow rightRow in rightRows)
                                {
                                    DataRow dr = result.NewRow();
                                    for (int i = 0; i < leftResultColumnArray.Length; i++)
                                    {
                                        dr[i] = leftRow[leftResultColumnArray[i].ColumnName];
                                    }
                                    for (int i = 0; i < rightResultColumnArray.Length; i++)
                                    {
                                        dr[leftResultColumnArray.Length + i] = rightRow[rightResultColumnArray[i].ColumnName];
                                    }

                                    result.Rows.Add(dr);
                                }
                            }
                        }
                    }
                    else if (joinType == JoinType.LeftJoin)
                    {
                        foreach (DataRow leftRow in ds.Tables[0].Rows)
                        {
                            DataRow[] rightRows = leftRow.GetChildRows(r);
                            if (rightRows.Length > 0)
                            {
                                foreach (DataRow rightRow in rightRows)
                                {
                                    DataRow dr = result.NewRow();
                                    for (int i = 0; i < leftResultColumnArray.Length; i++)
                                    {
                                        dr[i] = leftRow[leftResultColumnArray[i].ColumnName];
                                    }
                                    for (int i = 0; i < rightResultColumnArray.Length; i++)
                                    {
                                        dr[leftResultColumnArray.Length + i] = rightRow[rightResultColumnArray[i].ColumnName];
                                    }

                                    result.Rows.Add(dr);
                                }
                            }
                            else
                            {
                                DataRow dr = result.NewRow();

                                if (fillKeyColumn)
                                {
                                    for (int i = 0; i < rightKeyColumnArray.Length; ++i)
                                    {
                                        if (result.Columns.Contains(rightKeyColumnArray[i].ColumnName))
                                        {
                                            dr[rightKeyColumnArray[i].ColumnName] = leftRow[leftKeyColumnArray[i].ColumnName];
                                        }
                                    }
                                }

                                for (int i = 0; i < leftResultColumnArray.Length; i++)
                                {
                                    dr[i] = leftRow[leftResultColumnArray[i].ColumnName];
                                }

                                result.Rows.Add(dr);
                            }
                        }
                    }
                    else if (joinType == JoinType.RightJoin)
                    {
                        foreach (DataRow rightRow in ds.Tables[1].Rows)
                        {
                            DataRow[] leftRows = rightRow.GetParentRows(r);
                            if (leftRows.Length > 0)
                            {
                                foreach (DataRow leftRow in leftRows)
                                {
                                    DataRow dr = result.NewRow();
                                    for (int i = 0; i < leftResultColumnArray.Length; i++)
                                    {
                                        dr[i] = leftRow[leftResultColumnArray[i].ColumnName];
                                    }
                                    for (int i = 0; i < rightResultColumnArray.Length; i++)
                                    {
                                        dr[leftResultColumnArray.Length + i] = rightRow[rightResultColumnArray[i].ColumnName];
                                    }

                                    result.Rows.Add(dr);
                                }
                            }
                            else
                            {
                                DataRow dr = result.NewRow();

                                if (fillKeyColumn)
                                {
                                    for (int i = 0; i < leftKeyColumnArray.Length; ++i)
                                    {
                                        if (result.Columns.Contains(leftKeyColumnArray[i].ColumnName))
                                        {
                                            dr[leftKeyColumnArray[i].ColumnName] = rightRow[rightKeyColumnArray[i].ColumnName];
                                        }
                                    }
                                }

                                for (int i = 0; i < rightResultColumnArray.Length; i++)
                                {
                                    dr[leftResultColumnArray.Length + i] = rightRow[rightResultColumnArray[i].ColumnName];
                                }

                                result.Rows.Add(dr);
                            }
                        }
                    }
                    else if (joinType == JoinType.OutJoin)
                    {
                        foreach (DataRow leftRow in ds.Tables[0].Rows)
                        {
                            DataRow[] rightRows = leftRow.GetChildRows(r);
                            if (rightRows.Length > 0)
                            {
                                foreach (DataRow rightRow in rightRows)
                                {
                                    DataRow dr = result.NewRow();
                                    for (int i = 0; i < leftResultColumnArray.Length; i++)
                                    {
                                        dr[i] = leftRow[leftResultColumnArray[i].ColumnName];
                                    }
                                    for (int i = 0; i < rightResultColumnArray.Length; i++)
                                    {
                                        dr[leftResultColumnArray.Length + i] = rightRow[rightResultColumnArray[i].ColumnName];
                                    }

                                    result.Rows.Add(dr);
                                }
                            }
                            else
                            {
                                DataRow dr = result.NewRow();

                                if (fillKeyColumn)
                                {
                                    for (int i = 0; i < rightKeyColumnArray.Length; ++i)
                                    {
                                        if (result.Columns.Contains(rightKeyColumnArray[i].ColumnName))
                                        {
                                            dr[rightKeyColumnArray[i].ColumnName] = leftRow[leftKeyColumnArray[i].ColumnName];
                                        }
                                    }
                                }

                                for (int i = 0; i < leftResultColumnArray.Length; i++)
                                {
                                    dr[i] = leftRow[leftResultColumnArray[i].ColumnName];
                                }
                                result.Rows.Add(dr);
                            }
                        }

                        foreach (DataRow rightRow in ds.Tables[1].Rows)
                        {
                            DataRow[] leftRows = rightRow.GetParentRows(r);
                            if (leftRows.Length <= 0)
                            {
                                DataRow dr = result.NewRow();
                                if (fillKeyColumn)
                                {
                                    for (int i = 0; i < leftKeyColumnArray.Length; ++i)
                                    {
                                        if (result.Columns.Contains(leftKeyColumnArray[i].ColumnName))
                                        {
                                            dr[leftKeyColumnArray[i].ColumnName] = rightRow[rightKeyColumnArray[i].ColumnName];
                                        }
                                    }
                                }

                                for (int i = 0; i < rightResultColumnArray.Length; i++)
                                {
                                    dr[leftResultColumnArray.Length + i] = rightRow[rightResultColumnArray[i].ColumnName];
                                }

                                result.Rows.Add(dr);
                            }
                        }
                    }

                    result.EndLoadData();
                }

                return result;
            }

            public static DataTable Join(DataTable leftTable, DataTable rightTable, DataColumn[] leftKeyColumnArray, DataColumn[] rightKeyColumnArray, DataColumn[] leftResultColumnArray, DataColumn[] rightResultColumnArray, JoinType joinType, string prefixForDuplicatedColumn)
            {
                return Join(leftTable, rightTable, leftKeyColumnArray, rightKeyColumnArray, leftResultColumnArray, rightResultColumnArray, joinType, false, prefixForDuplicatedColumn);
            }

            public static DataTable Join(DataTable leftTable, DataTable rightTable, DataColumn leftKeyColumn, DataColumn rightKeyColumn, DataColumn[] leftResultColumnArray, DataColumn[] rightResultColumnArray, JoinType joinType, string prefixForDuplicatedColumn)
            {
                return Join(leftTable, rightTable, new DataColumn[] { leftKeyColumn }, new DataColumn[] { rightKeyColumn }, leftResultColumnArray, rightResultColumnArray, joinType, prefixForDuplicatedColumn);
            }

            public static DataTable Join(DataTable leftTable, DataTable rightTable, DataColumn leftKeyColumn, DataColumn rightKeyColumn, DataColumn[] leftResultColumnArray, DataColumn[] rightResultColumnArray, JoinType joinType, bool fillKeyColumn, string prefixForDuplicatedColumn)
            {
                return Join(leftTable, rightTable, new DataColumn[] { leftKeyColumn }, new DataColumn[] { rightKeyColumn }, leftResultColumnArray, rightResultColumnArray, joinType, fillKeyColumn, prefixForDuplicatedColumn);
            }

            public static DataTable Join(DataTable leftTable, DataTable rightTable, string leftKeyColumns, string rightKeyColumns, string leftResultColumns, string rightResultColumns, JoinType joinType, string prefixForDuplicatedColumn)
            {
                return Join(leftTable, rightTable, Parse(leftKeyColumns, leftTable), Parse(rightKeyColumns, rightTable), Parse(leftResultColumns, leftTable), Parse(rightResultColumns, rightTable), joinType, prefixForDuplicatedColumn);
            }

            public static DataTable Join(DataTable leftTable, DataTable rightTable, string leftKeyColumns, string rightKeyColumns, string leftResultColumns, string rightResultColumns, JoinType joinType, bool fillKeyColumn, string prefixForDuplicatedColumn)
            {
                return Join(leftTable, rightTable, Parse(leftKeyColumns, leftTable), Parse(rightKeyColumns, rightTable), Parse(leftResultColumns, leftTable), Parse(rightResultColumns, rightTable), joinType, fillKeyColumn, prefixForDuplicatedColumn);
            }

            private static DataColumn[] Parse(string columnNames, DataTable table)
            {
                DataColumn[] result;
                if (string.IsNullOrEmpty(columnNames) || columnNames == "*")
                {
                    result = new DataColumn[table.Columns.Count];
                    table.Columns.CopyTo(result, 0);
                }
                else
                {
                    string[] names = columnNames.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    result = new DataColumn[names.Length];
                    for (int i = 0; i < result.Length; i++)
                    {
                        result[i] = table.Columns[names[i]];
                    }
                }

                return result;
            }

            public static DataTable Top(DataTable dt, int top, string filterExpression, string sort)
            {
                DataRow[] drArray = dt.Select(filterExpression, sort);
                top = Math.Min(top, drArray.Length);
                DataTable result = dt.Clone();
                result.BeginLoadData();
                for (int i = 0; i < top; i++)
                {
                    result.ImportRow(drArray[i]);
                }
                result.EndLoadData();

                return result;
            }

            public static DataTable Top(DataTable dt, int top, string filterExpression, string sort, params string[] columnNames)
            {
                DataTable newTable = Select(dt, filterExpression, sort, columnNames);

                if (newTable.Rows.Count > top)
                {
                    DataTable result = newTable.Clone();

                    result.BeginLoadData();
                    for (int i = 0; i < top; i++)
                    {
                        result.ImportRow(newTable.Rows[i]);
                    }
                    result.EndLoadData();

                    return result;
                }
                else
                {
                    return newTable;
                }
            }

            public static DataTable Select(DataTable dt, string filterExpression, string sort)
            {
                DataView dv = new DataView(dt, filterExpression, sort, DataViewRowState.CurrentRows);
                return dv.ToTable();
            }

            public static DataTable Select(DataTable dt, string filterExpression, string sort, params string[] columnNames)
            {
                DataView dv = new DataView(dt, filterExpression, sort, DataViewRowState.CurrentRows);
                return dv.ToTable(false, columnNames);
            }

            public static DataTable Distinct(DataTable dt, params string[] columnNames)
            {
                return dt.DefaultView.ToTable(true, columnNames);
            }

            public static DataTable Trim(DataTable sourceTable, string sortColumn, params string[] checkColumns)
            {
                if (checkColumns == null || checkColumns.Length == 0)
                {
                    throw new ArgumentException("checkColumns can not be omitted.""checkColumns");
                }

                string condition = string.Join(" is not null or ", checkColumns);
                condition = condition + " is not null";

                DataView dv = new DataView(sourceTable);
                dv.Sort = sortColumn;
                dv.RowFilter = condition;
                if (dv.Count == 0)
                {
                    return sourceTable.Clone();
                }

                object startValue = dv[0].Row[sortColumn];
                object endValue = dv[dv.Count - 1].Row[sortColumn];

                DataView resultDv = new DataView(sourceTable);
                resultDv.RowFilter = string.Format("{0} >= '{1}' and {0} <= '{2}'", sortColumn, startValue, endValue);

                return resultDv.ToTable();
            }
        }

        public enum JoinType
        {
            InnerJoin,
            LeftJoin,
            RightJoin,
            OutJoin
        }
    }

           修改记录:2012-06-11 修改了由于重复列名导致的Right Join和Outer Join的bug。

                         2012-06-12 添加了一个重载,为Left Join、Right Join和Outer Join的空行绑定主键的值,相当于ISNULL(l.Key, R.Key)的效果。

  • 相关阅读:
    Python进阶: Decorator 装饰器你太美
    计算机网络自顶向下方法第3章-传输层 (Transport Layer).2
    Python进阶:值传递,引用传递?不存在的,是赋值传递
    Python进阶:对象复制与比较,分深浅,见真假
    Python基础:模块化来搭项目
    这说明一个问题
    我稍微思考了一下
    由LruCache和DiskLruCache提供三级缓存支持的ImageLoader
    回忆一个加塞方法
    三年六班的李子明同学,你妈拿了两本计算机基础在二号树上等你
  • 原文地址:https://www.cnblogs.com/Erik_Xu/p/1867591.html
Copyright © 2020-2023  润新知