为什么 DataTable.Select() 返回错误的行?

发布于 2024-10-29 13:44:45 字数 1728 浏览 5 评论 0原文

DataTable.Select() 函数使用这样的过滤器返回错误的行...

“booleanColumn1 AND booleanColumn2 AND GuidColumn1 = '00000000-0000-0000-0000-000000000000')”

对此格式进行几乎任何更改都可以修复它(请参阅例子)。在 dataView 上使用相同的过滤器可以正常工作。我很想将其更改为

“booleanColumn1 = 1 AND booleanColumn2 = 1 AND GuidColumn1 = '00000000-0000-0000-0000-000000000000')”

并声明它已修复(文档没有提及是“A”还是“A” = 1" 是布尔列的正确语法)。但也可以很容易地将责任归咎于 Guid 栏。在我重新访问代码库中数百个使用 DataTable.Select() 的地方之前,我希望看看是否有人知道到底发生了什么。

DataTable dt = new DataTable("dt");
dt.Columns.AddRange(new DataColumn[]
{
  new DataColumn("ID", typeof(Guid)),
  new DataColumn("A", typeof(bool)),
  new DataColumn("B", typeof(bool))
});

dt.Rows.Add(Guid.Empty, false, true);

// this incorrectly returns a row
Debug.WriteLine(dt.Select("B AND A AND ID = '00000000-0000-0000-0000-000000000000'").Length);

// yet it's fine for a DataView (correctly returns 0 rows)
DataView dv = new DataView(dt);
dv.RowFilter = "B AND A AND ID = '00000000-0000-0000-0000-000000000000'";
Debug.WriteLine(dv.Count);

// these correctly return 0 rows
Debug.WriteLine(dt.Select("B AND A").Length);
Debug.WriteLine(dt.Select("B AND A AND CONVERT(ID, 'System.String') = '00000000-0000-0000-0000-000000000000'").Length);
Debug.WriteLine(dt.Select("A AND B AND ID = '00000000-0000-0000-0000-000000000000'").Length);
Debug.WriteLine(dt.Select("B = 1 AND A AND ID = '00000000-0000-0000-0000-000000000000'").Length);
Debug.WriteLine(dt.Select("ID = '00000000-0000-0000-0000-000000000000' AND B AND A").Length);
Debug.WriteLine(dt.Select("B AND (A AND ID = '00000000-0000-0000-0000-000000000000')").Length);

// still wrong
Debug.WriteLine(dt.Select("B AND A AND ID = '00000000-0000-0000-0000-000000000000'").Length);

The DataTable.Select() function returns the wrong rows with a filter like this...

"booleanColumn1 AND booleanColumn2 AND GuidColumn1 = '00000000-0000-0000-0000-000000000000')"

Making virtually any alteration to this format fixes it (see example). Using the same filter on a dataView works correctly. I'm tempted to change it to

"booleanColumn1 = 1 AND booleanColumn2 = 1 AND GuidColumn1 = '00000000-0000-0000-0000-000000000000')"

and declare it fixed (the documentation makes no mention of whether "A" or "A = 1" is the correct syntax for boolean columns). But the blame could just as easily be placed on the Guid column. Before I revisit the hundreds of places we use DataTable.Select() in our codebase, I was hoping to see if anyone knew what was really going on.

DataTable dt = new DataTable("dt");
dt.Columns.AddRange(new DataColumn[]
{
  new DataColumn("ID", typeof(Guid)),
  new DataColumn("A", typeof(bool)),
  new DataColumn("B", typeof(bool))
});

dt.Rows.Add(Guid.Empty, false, true);

// this incorrectly returns a row
Debug.WriteLine(dt.Select("B AND A AND ID = '00000000-0000-0000-0000-000000000000'").Length);

// yet it's fine for a DataView (correctly returns 0 rows)
DataView dv = new DataView(dt);
dv.RowFilter = "B AND A AND ID = '00000000-0000-0000-0000-000000000000'";
Debug.WriteLine(dv.Count);

// these correctly return 0 rows
Debug.WriteLine(dt.Select("B AND A").Length);
Debug.WriteLine(dt.Select("B AND A AND CONVERT(ID, 'System.String') = '00000000-0000-0000-0000-000000000000'").Length);
Debug.WriteLine(dt.Select("A AND B AND ID = '00000000-0000-0000-0000-000000000000'").Length);
Debug.WriteLine(dt.Select("B = 1 AND A AND ID = '00000000-0000-0000-0000-000000000000'").Length);
Debug.WriteLine(dt.Select("ID = '00000000-0000-0000-0000-000000000000' AND B AND A").Length);
Debug.WriteLine(dt.Select("B AND (A AND ID = '00000000-0000-0000-0000-000000000000')").Length);

// still wrong
Debug.WriteLine(dt.Select("B AND A AND ID = '00000000-0000-0000-0000-000000000000'").Length);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忆伤 2024-11-05 13:44:45

这绝对是一个bug,而且看起来已经存在很长时间了。我发现这篇知识库文章描述了 .Net Framework 1.1 中完全相同的错误。

似乎第二个条件被完全忽略,因为我发现以下变体也返回一行:

dt.Select("B AND false AND ID = '00000000-0000-0000-0000-000000000000'")
dt.Select("B AND 0 AND ID = '00000000-0000-0000-0000-000000000000'")

然而,这正确地返回 0 行:

dt.Select("B AND A AND A AND ID = '00000000-0000-0000-0000-000000000000'")

This is definitely a bug, and it looks like it has been around for a long time. I found this knowledgebase article that describes the exact same bug in .Net framework 1.1.

It seems like the second condition is completely ignored, for I found that the following variations also return one row:

dt.Select("B AND false AND ID = '00000000-0000-0000-0000-000000000000'")
dt.Select("B AND 0 AND ID = '00000000-0000-0000-0000-000000000000'")

This however correctly returns 0 rows:

dt.Select("B AND A AND A AND ID = '00000000-0000-0000-0000-000000000000'")
微凉 2024-11-05 13:44:45

不是答案。

我修改了测试,使其更容易使用,发现更多不正确:

A AND B AND ID = '00000000-0000-0000-0000-000000000000'

B AND A AND (ID = '0000000-0000-0000-0000 -000000000000')

这对我来说看起来像是一个错误。您可能希望将其带到 Microsoft Connnect。

using System;
using System.Data;
using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        DataTable dt = new DataTable("dt")
        {
            Columns =
            {
              new DataColumn("ID", typeof(Guid)),
              new DataColumn("A", typeof(bool)),
              new DataColumn("B", typeof(bool)),
            }
        };

        dt.Rows.Add(Guid.Empty, false, false);
        dt.Rows.Add(Guid.Empty, false, true);
        dt.Rows.Add(Guid.Empty, true, false);
        dt.Rows.Add(Guid.Empty, true, true);

        Console.BackgroundColor = ConsoleColor.Black;
        Console.Clear();
        Console.ForegroundColor = ConsoleColor.Green;
        foreach (DataRow row in dt.Rows)
            Console.WriteLine("ID = {0}, A = {1}, B = {2}", row["ID"], row["A"], row["B"]);
        Console.WriteLine();

        // this incorrectly returns a row
        Test(dt, "B AND A AND ID = '00000000-0000-0000-0000-000000000000'");

        // these correctly return 0 rows
        Test(dt, "B AND A");
        Test(dt, "B AND A AND CONVERT(ID, 'System.String') = '00000000-0000-0000-0000-000000000000'");
        Test(dt, "A AND B AND ID = '00000000-0000-0000-0000-000000000000'");
        Test(dt, "B = 1 AND A AND ID = '00000000-0000-0000-0000-000000000000'");
        Test(dt, "ID = '00000000-0000-0000-0000-000000000000' AND B AND A");
        Test(dt, "B AND (A AND ID = '00000000-0000-0000-0000-000000000000')");
        Test(dt, "(B AND A AND ID = '00000000-0000-0000-0000-000000000000')");

        // still wrong
        Test(dt, "B AND A AND ID = '00000000-0000-0000-0000-000000000000'");

        // also incorrect for both A = True and B = True
        Test(dt, "B AND A AND (ID = '0000000-0000-0000-0000-000000000000')");

        if (Debugger.IsAttached)
        {
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.WriteLine();
            Console.WriteLine("Press any key to continue . . . ");
            Console.ReadKey();
        }

        Console.ResetColor();
        Console.Clear();
    }

    public static void Test(DataTable dt, string filter)
    {
        Console.ForegroundColor = ConsoleColor.White;
        Console.WriteLine(filter);
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine("    DT = {0}, DV = {1}",
            dt.Select(filter).Length,
            new DataView { Table = dt, RowFilter = filter }.Count);
    }
}

Not an answer.

I modified the test to make it a little easier to work with and found more incorrect:

A AND B AND ID = '00000000-0000-0000-0000-000000000000'

B AND A AND (ID = '0000000-0000-0000-0000-000000000000')

This looks like a bug to me. You might want to take it to Microsoft Connnect.

using System;
using System.Data;
using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        DataTable dt = new DataTable("dt")
        {
            Columns =
            {
              new DataColumn("ID", typeof(Guid)),
              new DataColumn("A", typeof(bool)),
              new DataColumn("B", typeof(bool)),
            }
        };

        dt.Rows.Add(Guid.Empty, false, false);
        dt.Rows.Add(Guid.Empty, false, true);
        dt.Rows.Add(Guid.Empty, true, false);
        dt.Rows.Add(Guid.Empty, true, true);

        Console.BackgroundColor = ConsoleColor.Black;
        Console.Clear();
        Console.ForegroundColor = ConsoleColor.Green;
        foreach (DataRow row in dt.Rows)
            Console.WriteLine("ID = {0}, A = {1}, B = {2}", row["ID"], row["A"], row["B"]);
        Console.WriteLine();

        // this incorrectly returns a row
        Test(dt, "B AND A AND ID = '00000000-0000-0000-0000-000000000000'");

        // these correctly return 0 rows
        Test(dt, "B AND A");
        Test(dt, "B AND A AND CONVERT(ID, 'System.String') = '00000000-0000-0000-0000-000000000000'");
        Test(dt, "A AND B AND ID = '00000000-0000-0000-0000-000000000000'");
        Test(dt, "B = 1 AND A AND ID = '00000000-0000-0000-0000-000000000000'");
        Test(dt, "ID = '00000000-0000-0000-0000-000000000000' AND B AND A");
        Test(dt, "B AND (A AND ID = '00000000-0000-0000-0000-000000000000')");
        Test(dt, "(B AND A AND ID = '00000000-0000-0000-0000-000000000000')");

        // still wrong
        Test(dt, "B AND A AND ID = '00000000-0000-0000-0000-000000000000'");

        // also incorrect for both A = True and B = True
        Test(dt, "B AND A AND (ID = '0000000-0000-0000-0000-000000000000')");

        if (Debugger.IsAttached)
        {
            Console.ForegroundColor = ConsoleColor.Gray;
            Console.WriteLine();
            Console.WriteLine("Press any key to continue . . . ");
            Console.ReadKey();
        }

        Console.ResetColor();
        Console.Clear();
    }

    public static void Test(DataTable dt, string filter)
    {
        Console.ForegroundColor = ConsoleColor.White;
        Console.WriteLine(filter);
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine("    DT = {0}, DV = {1}",
            dt.Select(filter).Length,
            new DataView { Table = dt, RowFilter = filter }.Count);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文