【问题标题】:Proper Syntax for LINQ query selecting only certain columns仅选择某些列的 LINQ 查询的正确语法
【发布时间】:2011-11-16 10:24:58
【问题描述】:

正确的语法是什么:

Dim qry As <??> = From f In dirInfo.GetFiles("*.QBW") Select File = f.FullName, Include = True
Dim dt As DataTable = qry.CopyToDataTable()

我尝试使用“IEnumerable(Of DataRow)”,但没有成功。在运行时它说:

无法转换类型的对象 'WhereSelectArrayIterator2[System.IO.FileInfo,VB$AnonymousType_02[System.String,System.Boolean]]' 输入 'System.Collections.Generic.IEnumerable`1[System.Data.DataRow]'。

【问题讨论】:

  • @Trikks,根据用法,这将是System.IO.DirectoryInfo 的一个实例。
  • @Anthony 是对的,dirInfo 是“System.IO.DirectoryInfo”
  • 啊,没错,错过了显而易见的事情。应该在描述中,虽然会节省我们一些时间! :)

标签: .net vb.net linq


【解决方案1】:

解决方案在您粘贴的错误消息中...您需要IEnumerable(Of FileInfo)

【讨论】:

  • 这是不正确的。 qry 不是Of FileInfo,涉及匿名类型。
  • 错误信息确实没有这么说。 Select 正在创建匿名类型的新实例。
  • 我会假设它是一个 IEnumerable(Of DataRow),其中每个 DataRow 包含 2 列:“文件”和“包含”。我怎样才能做到这一点?
  • 好,我只是这么想 - 如果我只选择一个字符串和布尔值,我将如何获得 FileInfo。
  • @Denis,DataRow 不参与查询,它永远不会是Of DataRow。对于这个特殊的问题,如果你想要一个DataTable,你可以手动创建它。创建表结构,然后遍历查询结果并添加新行。
【解决方案2】:
Dim qry = dirInfo.GetFiles("*.QBW").[Select](Function(f) New With { _
    f.FullName, _
    .Include = True _
})

【讨论】:

  • 但是我不能做 qry.CopyToDataTable()? “qry”是什么类型的?
  • qry 是一个 IEnumerable(匿名类型)。如果需要显式类型,请声明一个包含 2 个属性 FullName 和 Include 的新类。
  • 在这种情况下不能使用 CopyToDataTable。请参阅msdn.microsoft.com/en-us/library/5ycd1034(v=vs.80).aspx#Y662 向表中添加行
【解决方案3】:

或者干脆转Option Infer On,不要用任何东西,比如

Dim qry = From f In dirInfo.GetFiles("*.QBW") Select File = f.FullName, Include = True

查看here 进行更深入的讨论。

但是,要使用 CopyToDataTable() 类型需要 DataRow 派生类型。
您打算将 DataTable 用于什么用途,.net 中有很多地方不需要 DataTable?

【讨论】:

  • qry 的正确类型是什么?因为我似乎做不到 qry.CopyToDataTable()...
  • 这是一个匿名类型。编译器创建并维护它,并给它一个系统生成的名称(WhereSelectArray...]] 部分)。
【解决方案4】:

这是一个用c#编写的小解决方案

使用 select(x => new {})... 并将其键入为 IEnumerable

private static void Main(string[] args)
{
    var dirInfo = new DirectoryInfo(@"c:\windows\temp\");
    IEnumerable<dynamic> qry = dirInfo.GetFiles("*.txt").Select(x => new { x.FullName, x.Extension });

    foreach (var item in qry)
    {
        Console.WriteLine(string.Concat(item.Extension, " -> ", item.FullName));
    }
    Console.ReadKey();
}

编辑,这是vb版本

Private Shared Sub Main(args As String())
    Dim dirInfo = New DirectoryInfo("c:\windows\temp\")
    Dim qry As IEnumerable(Of dynamic) = dirInfo.GetFiles("*.txt").[Select](Function(x) New From { _
        x.FullName, _
        x.Extension _
    })

    For Each item As var In qry
        Console.WriteLine(String.Concat(item.Extension, " -> ", item.FullName))
    Next
    Console.ReadKey()
End Sub

更新 2

现在正如问题中明确指出的那样,打字不清楚,这可以通过使用 IEnumerable 来解决。但是,这不是最佳解决方案,相反,我建议构建一个对象并将您的数据存储在那里。但对于较小的应用程序,我想它会做。

【讨论】:

  • -1 用于发布对 VB.NET 问题的 C# 答案。此外,使用类型推断(通过使用 var 关键字)回避了实际提出的问题。第三,在我看来(但我不是 100% 确定)您使用 new { … } 改变了代码的含义。
  • 好吧,当我写下我的答案时,它被标记为 c#,因此我认为可以在 c# 中输入它......但是我已经用 vb.net 版本更新了帖子,所以每个人都会快乐如彩虹。从 .net4 开始,建议使用 Var 关键字,你生活在什么岩石下?这篇文章的意思是使用 linq 选择几个特定的​​列,而我所做的方式是我所知道的唯一方法。哦,请在批评之前告诉我们你想怎么做。
  • 这是在 C#/VB.NET 中作为交叉发布的,因为我不在乎答案是哪种语言。正在寻找这个想法。用 -1 标记 C# 答案是不公平的。 @Trikks,尽管没有必要,但感谢您将其更改为 VB.NET。
  • 已删除不赞成票...对此感到抱歉。但是,其他两点仍然成立。类型推断只是回避了这个问题,但并没有真正回答它。
  • 没错,我已经更新了帖子并进行了一些澄清。干杯:)
【解决方案5】:

我尝试在大多数情况下应用 Linq,因此我更熟悉它,但这似乎不是使用它的正确问题。所以回到古老而真实的方式......根据每个人的帮助,我认为最好的方法是:

  Dim dt As New DataTable()
  dt.Columns.Add("File", GetType(String))
  dt.Columns.Add("Include", GetType(Boolean))
  For Each f as FileInfo In dirInfo.GetFiles("*.QBW")
    dt.Rows.Add(f.FullName, True)
  Next

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    相关资源
    最近更新 更多