2016-01-16 96 views
0

我有以下方法:LINQ的聯盟操作

public IList<Book> Search(IList<int> genre) 
{  
    IQueryable<Book> books = database.Books; 
    if (genres.Count > 0) 
    { 
     books = books.Include("Genres"); 
     foreach (int genreId in genres) 
     { 
      books = books.Union(books.Where(b => b.Genres.Any(g => g.Id == genreId))); 
     } 
    } 
    return books.ToList() 
} 

其停止在最後一行的工作。爲什麼?也許有人知道更有效的方式來獲得屬於相應類型ID的所有實體?

+1

你是什麼意思由停止工作?該查詢在那個時間點被解析,所以如果查詢花費太長時間,它將一直呆在那裏,直到結果準備就緒。爲了更好地實現'.Contains' –

+0

如果你的意思是下一行在調試時不會運行,請在它之間放一個'try catch'並獲取異常消息以查看錯誤 –

+0

它顯示什麼錯誤? –

回答

2

我認爲你應該以相反的方式去做。即,從風格到書籍是這樣的:

return 
    database 
    .Genres 
    .Where(g => genre.Contains(g.Id)) 
    .SelectMany(g => g.Books) 
    .ToList(); 

此代碼假定存在是去從GenreBook這樣的導航屬性:

public class Genre 
{ 
    public Genre() 
    { 
     Books = new HashSet<Book>(); 
     //... 
    } 

    public virtual ICollection<Book> Books {get;set;} 
    //... Other properties here 
} 
0
public class Test 
{ 

    private List<Book> books = new List<Book>() 
    { 
     new Book 
     { 
      Id = 1, 
      Genres = new List<Genre>() 
      { 
       new Genre 
       { 
        Id = 1 
       }, 
       new Genre 
       { 
        Id = 2 
       } 
      } 
     }, 
     new Book 
     { 
      Id = 2, 
      Genres = new List<Genre>() 
      { 
       new Genre 
       { 
        Id = 3 
       } 
      } 
     } 
    }; 

    public IList<Book> Search(IList<int> genres) 
    { 

     return books.Where(x => x.Genres.Any(y => genres.Contains(y.Id))).ToList(); 

    } 

} 

做了一個簡單的例子。在函數中,Search只能用database.Books替換書。

測試驗證結果。

[TestClass] 
public class UnitTest1 
{ 

    Test t; 

    [TestInitialize] 
    public void TestInitialize() 
    { 
     t = new Test(); 
    } 

    [TestMethod] 
    public void TestGetBooksByGenre() 
    { 
     var result = t.Search(new List<int>() 
     { 
      1 
     }); 

     Assert.IsTrue(result.Count == 1); 
     Assert.IsTrue(result[0].Id == 1); 
    } 
}