在DataTable上使用Linq:选择特定列到datatable,而不是整个表。

10

我正在使用c#中的LINQ查询datatable

我想选择特定的列而不是整行,并将结果输入到datatable中。我该如何做呢?

我的代码:

public DataTable getConversions(string c_to, string p_to)
{
    var query = from r in matrix.AsEnumerable()
                where r.Field<string>("c_to") == c_to &&
                      r.Field<string>("p_to") == p_to
                select r;

    DataTable conversions = query.CopyToDataTable();

2
我收到一个错误:你收到了什么错误? - lc.
1
错误信息为: 在泛型类型或方法“System.Data.DataTableExtensions.CopyToDataTable<T>(System.Collections.Generic.IEnumerable<T>)”中,类型“AnonymousType#1”无法用作类型参数“T”。从“AnonymousType#1”到“System.Data.DataRow”的隐式引用转换不存在。 - Uri Klar
可能是使用带有LINQ查询的CopyToDataTable时出现异常?的重复问题。 - user166390
不完全是...我不是在寻找解决错误的方法,而是要正确选择一行中的两列并将结果输入到数据表中。 - Uri Klar
5个回答

10

如果您事先已经知道新数据表将有多少列,可以像这样操作:

DataTable matrix = ... // get matrix values from db

DataTable newDataTable = new DataTable();
newDataTable.Columns.Add("c_to", typeof(string));
newDataTable.Columns.Add("p_to", typeof(string));

var query = from r in matrix.AsEnumerable()
            where r.Field<string>("c_to") == "foo" &&
                    r.Field<string>("p_to") == "bar"
            let objectArray = new object[]
            {
                r.Field<string>("c_to"), r.Field<string>("p_to")
            }
            select objectArray;

foreach (var array in query)
{
    newDataTable.Rows.Add(array);
}

8

尝试使用最简单的访问DataTable方法,它可以帮助您完美地理解如何使用Linq访问DataTable和DataSet...

考虑下面的例子,假设我们有以下DataTable

DataTable ObjDt = new DataTable("List");
ObjDt.Columns.Add("WorkName", typeof(string));
ObjDt.Columns.Add("Price", typeof(decimal));
ObjDt.Columns.Add("Area", typeof(string));
ObjDt.Columns.Add("Quantity",typeof(int));
ObjDt.Columns.Add("Breath",typeof(decimal));
ObjDt.Columns.Add("Length",typeof(decimal));

这里是DatTable的代码,我们假设这个DataTable中有一些数据可用,并且我们需要通过处理某些数据来绑定特定的GridView,如下所示:

区域 | 数量 | 宽度 | 长度 | 价格=数量*宽度*长度

然后我们需要执行以下查询,以获得我们想要的精确结果。
var data = ObjDt.AsEnumerable().Select
            (r => new
            {
                Area = r.Field<string>("Area"),
                Que = r.Field<int>("Quantity"),
                Breath = r.Field<decimal>("Breath"),
                Length = r.Field<decimal>("Length"),
                totLen = r.Field<int>("Quantity") * (r.Field<decimal>("Breath") * r.Field<decimal>("Length"))
            }).ToList();

我们只需要将这个数据变量指定为数据源。

通过使用这个简单的Linq查询,我们可以获取所有的接受内容,并且我们也可以执行所有其他的LINQ查询......


使用lambda表达式加一。 - ashveli

8

在这里,我仅从mainDataTable中获取了三列特定的列,并使用过滤器

DataTable checkedParams = mainDataTable.Select("checked = true").CopyToDataTable()
.DefaultView.ToTable(false, "lagerID", "reservePeriod", "discount");

7

LINQ在处理列表方面比DataTable更加有效和易于使用。我可以看到上面的答案有循环(for, foreach),但我不太喜欢这种方式。

因此,从DataTable中选择特定列的最佳方法是使用DataView来过滤列,并将其用作所需的数据。

在这里查看如何操作。

DataView dtView = new DataView(dtYourDataTable);
DataTable dtTableWithOneColumn= dtView .ToTable(true, "ColumnA");

现在 DataTable dtTableWithOneColumn 只包含一列(ColumnA)。

3
您的选择语句返回的是一个匿名类型序列,而不是DataRow序列。CopyToDataTable()仅适用于IEnumerable<T>,其中T是DataRow或派生自DataRow的类型。您可以选择r行对象,然后在其上调用CopyToDataTable。
var query = from r in matrix.AsEnumerable()
                where r.Field<string>("c_to") == c_to &&
                      r.Field<string>("p_to") == p_to
                 select r;

DataTable conversions = query.CopyToDataTable();

您还可以实现CopyToDataTable,其中通用类型T不是DataRow。点击此处了解更多信息。

嗨。我知道我的代码是不正确的。问题是如何正确地选择仅两列而不是整行。 - Uri Klar
我已经在我的回答中添加了文章链接,以便执行此操作,http://msdn.microsoft.com/en-us/library/bb669096.aspx - Adil
我能否将类型保留为DataRow,但仅筛选特定列? - Uri Klar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接