2015-05-11 233 views
4

你好,我试图将下面的SQL语句转换成它的LINQ等价物,因为我对.net(编码一天)真的很陌生,现在我已经坚持了几个小时。SQL to IQueryable LINQ

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; } 
} 

我将不胜感激任何人的帮助。

编辑

Context类

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; } 

} 
+0

也不管你是否使用它或不要避免使用'Select *' –

+0

@bumble_bee_tuna是的,我意识到我使用该查询只是为了简单起见,当找出LINQ –

回答

3

你可以做这样的事情:

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); 
+0

它抱怨''BookID'不存在于'Contains()'之前的当前上下文中。 –

+0

@PavelKašelják请参阅编辑I添加'.Select(a => a.BookId))' –

+0

我这样做了,但它仍然抱怨这一行中的'BookID' Lnq.Books.Where(a => BookID.Contains'我添加了上下文类到我的问题 –

2

导航会让一切更简单。

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); 
+0

没有这个解决方案只是在'借用'表内选择?我需要根据用户借用的内容获取书籍,以便显示书籍的详细信息。我需要加入这两张桌子。然后返回'IQueryable '而不是'IQueryable ' –

+0

对不起,我在那里犯了一个小错误,它不是'SelectMany',而是'Select'。不,它投影书籍......因为您会首先注意到我们搜索由给定用户ID借来的书籍......那么一旦搜索缩小到所有的书籍,它将返回'IQueryable ',除了'Select'语句,然后'projects'实际的'Book' –

3

假设你的环境中称之为db,你可以做以下查询

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

这引发'System.InvalidOperationException'说'支持' LibraryContext的上下文自数据库创建以来已经发生了变化。“我真的没有得知它为什么这么做。 –

+0

@PavelKašelják看起来您正在使用实体框架,而不是LINQ to SQL,因为您的问题提示另外,您似乎已经对代码进行了架构更改,但尚未与现有数据库内容匹配。参考:http://stackoverflow.com/questions/21852121/the-model-backing-the-context-context-has-changed-since-the-database-was-cre和http://forums.asp.net /t/1998436.aspx?model+backing+the+context+has+changed+since+the+database+was+created+Consider+using+Code+First+Migrations+to+update+the+database以获取更多信息。 – Alex

+0

这个答案绝对是获得SQL的最简单方法,它与问题中的目标非常相似。 – Arkaine55

3

这可能是最好用加入做到这一点。

参数是:如果用户借了大量的书籍,或者数据有错误,那么你的子查询可能会返回很多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); 
+0

这确实可能是一个性能更好的查询。 – Alex

1

试试这个,

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

可以解释这是什么,为什么? –