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);
答案 0 :(得分:3)
这绝对是一个错误,它看起来已经存在了很长时间。我发现this knowledgebase article描述了.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'")
答案 1 :(得分:0)
不是答案。
我修改了测试,使其更容易使用,发现更多错误:
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);
}
}