![](/img/trans.png)
[英]Subquery in LINQ that's in the select statement, not the where clause
[英]Select statement on DataTable without where clause using Linq
我有一段代码需要处理一个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来解决这个问题。
fullTable
.AsEnumerable()
.Select(x => new
{
PartnerID = x.Field<int>("PartnerID"),
PartnerName = x.Field<string>("Partner Name")
})
.Distinct();
这将创建一个具有所需两个属性的匿名类型。 然后您将应用Distinct
删除重复项。 匿名类型为您处理GetHashCode
和Equals
, Distinct
用于标识重复项。
我们已经在这里得到了很好的答案,但是我认为这是一种更“预期”的方式。
除了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解决方案快很多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.