【问题标题】:Linq does not group in VB.NetLinq 不在 VB.Net 中分组
【发布时间】:2011-10-26 06:03:35
【问题描述】:

出于教育目的,我尝试将“Linq in action”一书中的以下 Linq 表达式转换为 VB.net

原始 C#

var list = 
  from book in SampleData.Books
  group book by new { book.Publisher.Name, book.Subject }
    into grouping
  select new {
    Publisher = grouping.Key.Publisher,
    Subject = grouping.Key.Subject,
    Book = grouping
  };

我的尝试:

Dim list = _books.GroupBy(Function(book) New With {.Publisher = book.Publisher.Name,
                                                    book.Subject}).
                  Select(Function(grouping) New With {.Publisher = grouping.Key.Publisher,
                                                      .Subject = grouping.Key.Subject,
                                                      .Books = grouping})

For Each item In list
  Console.WriteLine("Publisher:" & item.Publisher & ", Subject:" & item.Subject)
  For Each Book In item.Books
    Console.WriteLine("  " & Book.Title)
  Next
Next

这导致以下输出:

Publisher:FunBooks, Subject:Fun  
  Funny Stories  
Publisher:Joe Publishing, Subject:Work  
  LINQ rules  
Publisher:Joe Publishing, Subject:Work  
  C# on rails  
Publisher:Joe Publishing, Subject:Fun  
  All your base are belong to us  
Publisher:FunBooks, Subject:Fun  
  Bonjour mon Amour  

我希望“LINQ 规则”和“C# on rails”这本书以及“Funny Stories”和“Bonjour mon Amour”这本书被分组,因为它们具有相同的出版商和主题。 我的匿名密钥包含两个简单字符串的新对象。

我已经尝试在 SO 中搜索,但 other (or) 的答案并不能解决我的问题。在这种情况下,即使是像 telerikcarlosag 这样的代码翻译器也无济于事。

【问题讨论】:

    标签: linq c#-to-vb.net


    【解决方案1】:

    这就是问题所在:

    GroupBy(Function(book) New With {.Publisher = book.Publisher.Name,
                                      book.Subject})
    

    这不等同于 C# 版本,因为不幸的是,VB 在默认情况下在匿名类型中使用 可变 属性,并且可变属性不被视为哈希码或相等操作的一部分。您需要将这两个属性都设为“Key”属性:

    GroupBy(Function(book) New With {Key .Publisher = book.Publisher.Name,
                                     Key book.Subject})
    

    那么它应该可以正常工作。您可以在 VB on MSDN 中阅读有关匿名类型的更多信息。

    【讨论】:

    • 是的,这很好用;多谢!哇,乔恩·斯基特本人的回答。我感到很荣幸。 :-)
    • 我在 LINQPad 中测试了因此失败的查询,并使用了 LINQ to Entities 源。在我的代码中,我实际上是在具体化查询(ToList)并从中运行组查询,因为我必须在此期间进行一些每行计算。这使我相信这是 LINQ to Objects 而不是 LINQ to Entities 中的问题。我假设这是因为在 LINQ to Entities 中,分组表达式被转换为 TSQL,而在 LINQ to Objects 中,哈希码用于组键相等。这听起来正确吗?
    • @pseudocoder:不,这与哈希码无关 - 它与用于确定相等性的属性有关。听起来 LINQ to Entities 将 all 属性视为关键属性......这对我来说听起来像是一个错误。这不是 LINQ to Objects 中的“问题”——这只是 VB 中匿名类型如何工作的问题。
    【解决方案2】:

    虽然我对您翻译这些示例的努力表示赞赏,但实际上,我们可以从 Manning 网站:http://www.manning.com/marguerie/ 下载 C# 和 VB 中的所有 LINQ in Action 示例。此外,我们还在 LinqPad 示例中添加了示例,以便您轻松尝试示例并保存您的更改。有关如何访问它的说明,请参阅 http://www.thinqlinq.com/Default/LINQ-In-Action-Samples-available-in-LINQPad.aspx

    看来您正在处理示例 5.06b。稍微更新一下,我们的VB翻译是:

    Dim query = _
      From book In SampleData.Books _
      Group book.Title By book.Publisher, book.Subject Into grouping = Group _
      Select _
        Publisher = Publisher.Name, _
        Subject = Subject.Name, _
        Titles = grouping 
    

    如果您想使用 Lambda 语法,您确实需要将 Key 指定为 @johnskeet 所示:

    Dim list = SampleData.Books.GroupBy(Function(book) New With { 
                              Key .Publisher = book.Publisher.Name, 
                              Key .Subject = book.Subject}). 
                   Select(Function(grouping) New With {
                      .Publisher = grouping.Key.Publisher, 
                      .Subject = grouping.Key.Subject, 
                      .Books = grouping}) 
    

    【讨论】:

    • 好的,作者本人... :-) 感谢 linq-links 和代码 sn-ps。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多