【问题标题】:LINQ IQueryable Nested LoopsLINQ IQueryable 嵌套循环
【发布时间】:2019-06-25 22:34:37
【问题描述】:

我正在尝试将此循环复制为 IQueryable:

        foreach (var book in BookList)
        {
            foreach (var a in book.Authors)
            {
                if (a.AuthorId.ToString() == Id)
                {
                    AuthorView = new AuthorViewModel(a, item.BookId);
                }
            }
        }

我试过了:

var Test = _context.Book.Include(x => x.Authors)
  SelectMany(y => y.Authors).ToList().FirstOrDefault(x => x.AuthorId.ToString() == Id)
.Select(x => new AuthorViewModel(x, ??.BookId);

但是我在尝试创建 AuthorViewModel 对象时遇到了困难,因为它需要我无法再访问的 BookId。有没有办法传递书的ID?

对不起,仅仅发布示例没有意义。

Books 是数据库中的一个表。 Authors 是数据库中的一个表,其中包含许多作者。

Book:
BookId
Authors

Authors:
AuthorId
Name
DOB

AuthorList 应该是 BookList(列表)。我已经更正了。

我正在尝试根据作者 ID 定位作者 - 并将其返回一个对象(作者、BookId(来自图书表))

【问题讨论】:

  • 你能分享AuthorList类型吗?
  • 为什么是a.AuthorId.ToString() == Id?如果基础类型是数字,则将参数更改为正确的类型并写入a.AuthorId == Id。这非常重要。强制转换为字符串会阻止使用任何涵盖AuthorId 的索引。如果Id包含前导0或空格,则比较失败
  • 您的循环显示了一件事,而查询则完全不同。你到底想做什么?解释你想要什么,而不是你如何尝试实现它。您想要为每本书和作者单独记录吗?或者只是每本书的第一作者?

标签: asp.net linq


【解决方案1】:

这是我会做的:

var id= int.Parse(Id);
var Test = _context.Book.Include(x => x.Authors)
                        .SelectMany(item => item.Authors
                                                .Where(y => y.AuthorId == id)
                                                .Select(b => new AuthorViewModel(b,item.BookId));

您可以在 SelectMany 扩展方法中进行过滤和投影

【讨论】:

  • 谢谢 - 我最初正在做与此非常相似的事情。原来我需要添加 '.First()' 以将其从 IQueryable 转换为我想要的对象。
  • 不客气,SelectMany 是将集合扁平化为单个集合,但您也可以将其视为 sql 中的交叉连接,因此在内部集合的操作中您可以使用根对象
【解决方案2】:

我认为你根本不需要SelectManyInclude。你可以去喜欢;

_context.Book
    .Where(b => b.Authors.Any(a => a.AuthorId.ToString() == Id))
    .Select(b => new AuthorViewModel(b.Authors.FirstOrDefault(x => x.AuthorId.ToString() == Id), b.BookId);

【讨论】:

    【解决方案3】:

    如果您深入研究作者 (SelectMany),那么您将无法返回书籍。 AuthorId 的条件需要在内部处理。

    var Test = _context.Book.Include(x => x.Authors)
              .FirstOrDefault(x => x.Authors.Any(y => y.AuthorId.ToString() == Id))
              .Select(x => new AuthorviewModel(x,x.BookId);
    

    当然,这将只为每位作者选择一本书,就像您的代码一样。我想知道你想要的行为是不是把所有的书都拿来......

    【讨论】:

      【解决方案4】:

      首先,将Id 转换为数字,而不是尝试将AuthorId 转换为字符串。对表字段应用任何类型的函数意味着不能使用覆盖它的索引。与基于 ID 的快速搜索不同,您将进行全表扫描,在使用 string 语义进行比较之前将值转换为字符串。如果Id 参数包含任何前导零,则比较将失败。

      对于 LINQ 查询本身,最简单的方法是使用查询表单。如果你想为每本书和作者组合返回一条记录,你可以这样写:

      var id=int.Parse("ID");
      
      var query= from book in _context.Book
                 from author in book.Authors
                 where author.AuthorID = id
                 select new AuthorViewModel(author,book.BookId);
      var records=query.ToList();
      

      【讨论】:

      • 谢谢 - 我以后会转换成 int :)
      猜你喜欢
      • 1970-01-01
      • 2023-03-28
      • 2023-03-17
      • 2019-03-27
      • 2016-06-23
      • 2017-02-19
      • 2011-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多