我有一段代码需要处理一个DataTable。 DataTable看起来像这样:
PartnerID | Partner Name | GroupID | Group Name | Description
------------------------------------------------------------------------------------------
1 | First Name | 4 | Group Name1 | Foo
2 | Second Name | 12 | Group Name2 | Bar
3 | Third Name | 7 | Group Name3 | Hello
3 | Third Name | 8 | Group Name4 | Hello World
现在我要完成的是以下SQL语句的性能:
SELECT DISTINCT PartnerID, Partner Name
FROM Table1
在使用Linq的C#中,预期输出如下:
PartnerID | Partner Name |
-------------------------------------
1 | First Name |
2 | Second Name |
3 | Third Name |
我已经看过以下帖子:
并且发现这对我的情况无济于事,因为我真正想做的就是获取指定的列,但是那里的所有答案都显示了一个解决方案,该解决方案似乎只在where语句中工作或默认情况下选择所有列。
我当前的代码现在看起来像这样:
static void Main(string[] args)
{
DataTable fullTable = new DataTable();
AddColumns(fullTable, "PartnerID", "Partner Name", "GroupID", "Group Name", "Description");
fullTable.Rows.Add(1, "First Name", 4, "Group Name1", "Foo");
fullTable.Rows.Add(2, "Second Name", 12, "Group Name2", "Bar");
fullTable.Rows.Add(3, "Third Name", 7, "Group Name3", "Hello");
fullTable.Rows.Add(3, "Third Name", 8, "Group Name4", "Hello World");
var selectTwoCols = from arow in fullTable.AsEnumerable()
select arow; //how do i select specific columns from those rows?
foreach (DataRow dataRow in selectTwoCols.Rows)
{
foreach (var item in dataRow.ItemArray)
{
Console.Write(item + " ");
}
Console.WriteLine();
}
}
static void AddColumns(DataTable table, params string[] columnNames)
{
for (int i = 0; i < columnNames.Length; i++)
{
table.Columns.Add(columnNames[i]);
}
}
我也愿意使用不同的类,尽管我仍然很想知道如何使用DataTables来解决这个问题
答案 0 :(得分:4)
fullTable
.AsEnumerable()
.Select(x => new
{
PartnerID = x.Field<int>("PartnerID"),
PartnerName = x.Field<string>("Partner Name")
})
.Distinct();
这将创建具有所需两个属性的匿名类型。然后,您应用Distinct
来删除重复项。匿名类型为您处理GetHashCode
用于标识重复项的Equals
和Distinct
。
答案 1 :(得分:0)
我们已经在这里得到了很好的答案,但是我认为这是一种更“预期”的方式。
除了DataTable类之外,C#还提供了DataView类。
在该类文档中,我们可以阅读以下内容:
表示用于排序的DataTable的可绑定数据的自定义视图, 过滤,搜索,编辑和导航。
因此,从这一点来看,我认为Microsoft打算将此类与DataTable结合使用,以过滤出行或列以及文档中提到的几乎所有操作。
所以我用
DataView view = new DataView(fullTable);
DataTable twoColsDistinct = view.ToTable(true, "PartnerID", "Partner Name"); //distinct
DataTable twoColsNonDistinct = view.ToTable(false, "PartnerID", "Partner Name"); //not distinct
要获取仅选择了两个必需列的两个DataTables并打印这两个datatables的内容,将导致以下输出:
two cols distinct
----------------------
1 First Name
2 Second Name
3 Third Name
----------------------
two cols non distinct
----------------------
1 First Name
2 Second Name
3 Third Name
3 Third Name
这正是我所需要的。只是选择列。
使用以下代码可得到完全相同的输出:
var query = fullTable
.AsEnumerable()
.Select(x => new
{
PartnerID = x.Field<string>("PartnerID"),
PartnerName = x.Field<string>("Partner Name")
}
).Distinct();
foreach(var t in query)
{
Console.WriteLine(t.PartnerID + " " + t.PartnerName);
}
打印
1 First Name
2 Second Name
3 Third Name
尽管我个人更喜欢上面的更紧凑的解决方案,因为使用“更长”的解决方案,我们正在创建自定义对象(更确切地说是匿名类型),而PartnerID和PartnerName则成为对象实例变量,在我的“简单”案例中,首先,我没有处理任何面向对象的“东西”。
我发现紧凑的解决方案更易于阅读和理解。
奖金:
我们可以使用相同的DataView对象来创建过滤后的DataTable,这可能有用也可能无效:
view.RowFilter = "PartnerID > 1";
DataTable partnerIdGreaterThanOne = view.ToTable(true);
打印此数据表将输出以下内容:
2 Second Name 12 Group Name2 Bar
3 Third Name 7 Group Name3 Hello
3 Third Name 8 Group Name4 Hello World
不确定在这里使用Linq是否更好。只是想把它扔在那里。
编辑:
我做了一些性能测试,发现是使用
var query = fullTable
.AsEnumerable()
.Select(x => new
{
PartnerID = x.Field<string>("PartnerID"),
PartnerName = x.Field<string>("Partner Name")
})
.Distinct();
比不需要DataView方法创建的其他DataTable对象的DataView解决方案要快得多。