当前位置:编程学习 > C#/ASP.NET >>

发现了DataTable的一个bug

以下函数可保留选定列:
         public static void FilterColumn(this DataTable table, params string[] reserveColumnNames)
         {
             HashSet<string> needColNameSet = new HashSet<string>(reserveColumnNames);

             List<string> colNameList = new List<string>(table.Columns.Count);
             foreach (DataColumn col in table.Columns)
                 colNameList.Add(col.ColumnName);

             table.AcceptChanges();
             foreach (string columnName in colNameList)
             {
                 if (needColNameSet.Contains(columnName) == false)
                     table.Columns.Remove(columnName);
             }
             table.AcceptChanges();
         }


随便构建一个DataTable,如:

DataTable table = new DataTable();
table.Columns.Add("One",typeof(int));
table.Columns.Add("Two",typeof(int));
table.Columns.Add("Three",typeof(int));


执行:
DataRow[] rows = table.Select("Three=1");

无误,然后执行以下代码:
FilterColumn(table, "One", "Three");

再次执行:
DataRow[] rows = table.Select("Three=1");


报错:引发了“System.IndexOutOfRangeException”类型的异常 System.Data.DataRow[] {System.IndexOutOfRangeException}

StackTrack:
   在 System.Data.Select.CompareClosestCandidateIndexDesc(Int32[] id)
   在 System.Data.Select.FindClosestCandidateIndex()
   在 System.Data.Select.SelectRows()
   在 System.Data.DataTable.Select(String filterExpression) bug DataTable RemoveColumn Select --------------------编程问答-------------------- Three列 已经删除 还做什么筛选? --------------------编程问答--------------------
引用 1 楼 Return_false 的回复:
Three列 已经删除 还做什么筛选?

没有啊,"One"和"Three"是保留的列,"two"被删除了。 --------------------编程问答-------------------- 完全copy你的代码运行了一下,没发现报错 --------------------编程问答--------------------  重复索引么
 不是已经有Three 再加个就溢出了 --------------------编程问答-------------------- 没抱错的飘过1` --------------------编程问答-------------------- 把foreach (string columnName in colNameList)              {                  if (needColNameSet.Contains(columnName) == false)                      table.Columns.Remove(columnName);              }              table.AcceptChanges(); 

这段代码注释,再调试看看!! --------------------编程问答-------------------- 看错了,不好意思
试了一下,代码应该没有问题吧 --------------------编程问答-------------------- 可以确定的是:
1。 从你目前给出的代码,是没有错误的
2。 这也不是什么datatable的BUG

namespace ConsoleApplication2
{
    static class Program
    {
        static void Main(string[] args)
        {
            DataTable table = new DataTable();
            table.Columns.Add("One", typeof(int));
            table.Columns.Add("Two", typeof(int));
            table.Columns.Add("Three", typeof(int));

            DataRow[] rows = table.Select("Three=1");

            foreach (DataColumn item in table.Columns)
            {
                Console.WriteLine(item.ColumnName);
            }

            // table.FilterColumn("One", "Three");  //recommand you use FilterColumn this way
            FilterColumn(table, "One", "Three");
          
            foreach (DataColumn item in table.Columns)
            {
                Console.WriteLine(item.ColumnName);
            }

            DataRow[] rows1 = table.Select("Three=1");
            foreach (DataColumn item in table.Columns)
            {
                Console.WriteLine(item.ColumnName);
            }

            Console.ReadKey();
        }

        public static void FilterColumn(this DataTable table, params string[] reserveColumnNames)
        {
            HashSet<string> needColNameSet = new HashSet<string>(reserveColumnNames);

            List<string> colNameList = new List<string>(table.Columns.Count);
            foreach (DataColumn col in table.Columns)
                colNameList.Add(col.ColumnName);

            table.AcceptChanges();
            foreach (string columnName in colNameList)
            {
                if (needColNameSet.Contains(columnName) == false)
                    table.Columns.Remove(columnName);
            }
            table.AcceptChanges();
        }
    }

    
}
--------------------编程问答-------------------- 经过测试没发现报错! --------------------编程问答--------------------
引用 5 楼 coobai 的回复:
没抱错的飘过1`

Sorry,帖子有误,应该是从DB load出来的table,

更正代码如下:

DataTable table = new DataTable();
using (IDataReader rd = GetTableFromDB())
{
    table.Load(rd);
}


DB是一个含One,Two,Three散列的表 --------------------编程问答--------------------
引用 8 楼 q107770540 的回复:
可以确定的是:
1。 从你目前给出的代码,是没有错误的
2。 这也不是什么datatable的BUG

namespace ConsoleApplication2
{
    static class Program
    {
        static void Main(string[] args)
        {
            DataTable table = new DataTable();
            table.Columns.Add("One", typeof(int));
            table.Columns.Add("Two", typeof(int));
            table.Columns.Add("Three", typeof(int));

            DataRow[] rows = table.Select("Three=1");

            foreach (DataColumn item in table.Columns)
            {
                Console.WriteLine(item.ColumnName);
            }

            // table.FilterColumn("One", "Three");  //recommand you use FilterColumn this way
            FilterColumn(table, "One", "Three");
          
            foreach (DataColumn item in table.Columns)
            {
                Console.WriteLine(item.ColumnName);
            }

            DataRow[] rows1 = table.Select("Three=1");
            foreach (DataColumn item in table.Columns)
            {
                Console.WriteLine(item.ColumnName);
            }

            Console.ReadKey();
        }

        public static void FilterColumn(this DataTable table, params string[] reserveColumnNames)
        {
            HashSet<string> needColNameSet = new HashSet<string>(reserveColumnNames);

            List<string> colNameList = new List<string>(table.Columns.Count);
            foreach (DataColumn col in table.Columns)
                colNameList.Add(col.ColumnName);

            table.AcceptChanges();
            foreach (string columnName in colNameList)
            {
                if (needColNameSet.Contains(columnName) == false)
                    table.Columns.Remove(columnName);
            }
            table.AcceptChanges();
        }
    }

    
}


谢谢,是我说错了,应该是从DB load出来的table,见:

例如:

DataTable table = new DataTable();
using (IDataReader rd = GetTableFromDB())
{
    table.Load(rd);
}

然后执行删除列的操作,删除后如果对原始列的顺序有影响的(如中间某列),select就就怎么样都不能执行。谢谢提醒,正在看table.Load给列加了什么特别的属性。 --------------------编程问答-------------------- --------------------编程问答--------------------
引用 8 楼 q107770540 的回复:
可以确定的是:
1。 从你目前给出的代码,是没有错误的
2。 这也不是什么datatable的BUG

namespace ConsoleApplication2
{
    static class Program
    {
        static void Main(string[] args)
        {
            DataTable table = new DataTable();
            table.Columns.Add("One", typeof(int));
            table.Columns.Add("Two", typeof(int));
            table.Columns.Add("Three", typeof(int));

            DataRow[] rows = table.Select("Three=1");

            foreach (DataColumn item in table.Columns)
            {
                Console.WriteLine(item.ColumnName);
            }

            // table.FilterColumn("One", "Three");  //recommand you use FilterColumn this way
            FilterColumn(table, "One", "Three");
          
            foreach (DataColumn item in table.Columns)
            {
                Console.WriteLine(item.ColumnName);
            }

            DataRow[] rows1 = table.Select("Three=1");
            foreach (DataColumn item in table.Columns)
            {
                Console.WriteLine(item.ColumnName);
            }

            Console.ReadKey();
        }

        public static void FilterColumn(this DataTable table, params string[] reserveColumnNames)
        {
            HashSet<string> needColNameSet = new HashSet<string>(reserveColumnNames);

            List<string> colNameList = new List<string>(table.Columns.Count);
            foreach (DataColumn col in table.Columns)
                colNameList.Add(col.ColumnName);

            table.AcceptChanges();
            foreach (string columnName in colNameList)
            {
                if (needColNameSet.Contains(columnName) == false)
                    table.Columns.Remove(columnName);
            }
            table.AcceptChanges();
        }
    }

    
}

能不能QQ回我一句  --------------------编程问答-------------------- 为什么我运行没报错? --------------------编程问答--------------------
Quote: 引用 13 楼 zhangyuxia8 的回复:

你QQ多少? --------------------编程问答-------------------- 引用 楼主 madaming 的回复:
 ObjectQuery<T>.Include 方法include的实体怎样排序  具体实例:       return this.ObjectContext.题库集.Include("背记题"); “题库集”与"背记题"是一对多关联,那么在include中德"题库集"怎样排序。  
--------------------编程问答-------------------- 多半是你的问题 --------------------编程问答-------------------- 表示没报错! --------------------编程问答-------------------- 除 --------------------编程问答--------------------
         过滤列有个更好的方法,如下:

           DataTable dt = new DataTable();
           //构建数据略.......
           DataView dv = dt.DefaultView;
           DataTable filterDt = dv.ToTable(true, "One,Three");
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,