【问题标题】:SQL to IQueryable LINQSQL 到 IQueryable LINQ
【发布时间】:2015-05-11 02:40:53
【问题描述】:

您好,我正在尝试将以下 SQL 语句转换为其等效的 LINQ 语句,由于我对 .net 非常陌生(编码一天),我已经被困在这几个小时了。

SELECT * 
 FROM Books 
 WHERE BookID IN (SELECT BookID 
              FROM Borrows 
              WHERE UserID = 2) 

这是模型

public class LibUser
{       
    [Key]
    public int UserID { get; set; }
    [Required, StringLength(50), Display(Name = "First Name")]
    public string UserFirstName { get; set; }
    [Required, StringLength(50), Display(Name = "Last Name")]
    public string UserLastName { get; set; }
    [Required, StringLength(10000), Display(Name = "Residence"), DataType(DataType.MultilineText)]
    public string Adress { get; set; }
}

public class Book { 
    [Key]
    public int BookID { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
    public DateTime Published{ get; set; }
}

public class Borrowed {
    [Key]
    public int BorrowID { get; set; }
    public int UserID { get; set; }
    public int BookID { get; set; } 
}

非常感谢任何人的帮助。

编辑

上下文类

public class LibraryContext : DbContext
{

          public LibraryContext()
        : base("libromatic")
    {
    }

    public DbSet<LibUser> LibUsers { get; set; }
    public DbSet<Book> Books { get; set; }
    public DbSet<Borrowed> Borrows { get; set; }

}

【问题讨论】:

  • 另外,无论你是否使用它,都避免使用Select *
  • @bumble_bee_tuna 是的,我意识到我在计算 LINQ 时使用该查询只是为了简单起见

标签: c# sql asp.net-mvc linq


【解决方案1】:

假设您的上下文称为db,您可以执行以下查询

var borrowedBooksForUser = db.Books
     .Where(b => db.Borrowed.Any(x => x.UserID == 2 && x.BookID == b.BookID));

【讨论】:

  • 这会抛出System.InvalidOperationExceptionThe model backing the 'LibraryContext' context has changed since the database was created. 我真的不知道它为什么这样做。
  • @PavelKašelják 看来您使用的是实体框架,而不是您的问题所建议的 LINQ to SQL 此外,您似乎在代码中进行了架构更改,与现有的数据库内容不匹配。请参阅:stackoverflow.com/questions/21852121/…forums.asp.net/t/… 了解更多信息。
  • 这个答案绝对是获取 SQL 的最简单方法,它与问题中给出的目标非常相似。
  • @Arkaine55,是的,尽管在书 id 上使用连接条件时存在其他可能的查询,这将产生相同的结果
【解决方案2】:

最好使用连接来执行此操作。

论据是:如果用户借了大量书籍,或者数据有错误,那么您的子查询可能会返回大量 ID,而长列表上的 SQL 'IN' 子句会变得非常慢。

使用连接:

SQL 查询:

SELECT Books.* FROM Books 
  JOIN Borrows ON Borrows.BookID = Books.BookID
  WHERE Borrows.UserID = 2 

Linq 语句:

var allBooksBorrowedByUser2 = db.Borrowed
                .Where(borrow => borrow.UserID == 2)
                .Join(db.Books,
                      borrow => borrow.BookID,
                      book => book.BookID,
                      (borrow, book) => book);

【讨论】:

  • 在一般情况下,这确实是一个性能更好的查询。
【解决方案3】:

导航会让一切变得更简单。

public class Borrowed {
    [Key]
    public int BorrowID { get; set; }
    public int UserID { get; set; }
    public int BookID { get; set; } 

    // Navigation Properties
    public virtual LibUser User { get; set; }
    public virtual Book Book { get; set; }
}

Borrows.Where(borrow => borrow.UserId == 2)
       .Select(borrow => borrow.Book);

【讨论】:

  • 此解决方案是否仅在 Borrows 表内进行选择?我需要根据用户借阅的内容获取书籍,以便显示书籍详细信息。我需要加入这两个表。然后返回IQueryable&lt;Book&gt; 而不是IQueryable&lt;Borrowed&gt;
  • 对不起,我犯了一个小错误,不是SelectMany,而是Select。不,它会投影书籍...您会注意到,首先我们搜索给定用户 ID 借用的书籍...然后一旦搜索范围缩小到所有书籍,它将返回 IQueryable&lt;Borrowed&gt;,除了 out Select 声明然后是projects 实际的Book
【解决方案4】:

你可以这样做:

var Lnq = new LinqDataContext();
var borrowId = Lnq.Borrowed.Where(a => a.UserID == 2).Select(a => a.BookID).ToList();

var bookQuery = Lnq.Books.Where(a => borrowId.Contains(a.BookID))
                         .Select(a => a.YourColumn);

【讨论】:

  • 它抱怨BookIDContains() 之前的当前上下文中不存在
  • @PavelKašelják 查看我所做的编辑,添加.Select(a =&gt; a.BookId))
  • 我这样做了,但它仍然抱怨这一行中的BookID Lnq.Books.Where(a =&gt; BookID.Contains 我将上下文类添加到我的问题中
  • 只是要注意最近的编辑实际上已经使这 2 个单独执行的查询与第二个本质上传递 ("SELECT BookID FROM Borrows WHERE UserID = 2") 的结果作为复杂的 where 子句。 stackoverflow.com/questions/7897630/…
  • @Arkaine55 是的,我试图让它对他来说更具可读性
【解决方案5】:

试试这个,

  var getResult=from b in db.Books
  join bo in db.Borrows on b.BookID=bo.BookID
  where bo.UserID=2 

【讨论】:

  • 能解释一下这是什么,为什么?
猜你喜欢
  • 2013-10-03
  • 1970-01-01
  • 2014-12-11
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 2017-02-22
  • 2020-04-23
  • 1970-01-01
相关资源
最近更新 更多