我意識到我不完全理解LINQ-to-Entities中的Include
方法。與LINQ到實體的奇怪行爲包括
例如,下面的兩個代碼片段。我期望他們產生相同的輸出(儘管第一個版本可能更高效,因爲它避免了JOIN
s)。
// Snippet 1
using (var db = new Db()) {
var author = db.Authors.First();
db.LoadProperty<Author>(author, o => o.Books);
foreach (var book in author.Books) {
db.LoadProperty<Book>(book, o => o.Editions);
foreach (var edition in book.Editions)
Response.Write(edition.Id + " - " + edition.Title + "<br />");
}
}
Response.Write("<br />");
// Snippet 2
using (var db = new Db()) {
var author = db.Authors.Include("Books.Editions").First();
foreach (var book in author.Books) {
foreach (var edition in book.Editions)
Response.Write(edition.Id + " - " + edition.Title + "<br />");
}
}
但輸出爲每個代碼段不同的是:
1 - Some Book First Edition
2 - Another Book First Edition
3 - Another Book Second Edition
4 - Another Book Third Edition
8 - Some Book First Edition
9 - Another Book First Edition
第一片段正確地輸出{Edition Id} - {Edition Title}
,而第二個意外打印{Book Id} - {Edition Title}
和只給出了每本書的第一版本。
發生了什麼事?有沒有一種方法可以使用Include
來實現所需的輸出?
EDIT 1:MySQL數據看起來像(校正):
Authors = { { Id = 1, Name = "Some Author" } }
Books = { { Id = 8, AuthorId = 1 },
{ Id = 9, AuthorId = 1 } }
Editions = { { Id = 1, Title = "Some Book First Edition" },
{ Id = 2, Title = "Another Book First Edition" },
{ Id = 3, Title = "Another Book Second Edition" },
{ Id = 4, Title = "Another Book Third Edition" } }
EditionsInBooks = { { BookId = 8, EditionId = 1 },
{ BookId = 9, EditionId = 2 },
{ BookId = 9, EditionId = 3 },
{ BookId = 9, EditionId = 4 } }
注意,沒有用Edition
或Id = 8
。
而上面的代碼是我的完整代碼,在Page_Load
中爲空的測試頁。
編輯2:我已經測試了以下,他們不有所作爲:
var author = db.Authors.Include("Books.Editions").AsEnumerable().First();
var author = db.Authors.Include("Books.Editions").Single(o => o.Id == 1);
var author = db.Authors.Include("Books").Include("Books.Editions").First();
編輯3:如果我啓用延遲加載,以下工作(在代碼段2中):
var author = db.Authors.First();
(這實質上執行相同片段1,我想。)
然而,這仍返回奇怪輸出而不管延遲加載:
var author = db.Authors.Include("Books.Editions").First();
EDIT 4 :我很抱歉,但我錯誤地表述了上面的表格結構。 (我有一個這樣的日子。)現在已經糾正了,以顯示多對多的關係。請參閱編輯1.
而且輸出爲
((ObjectQuery)db.Authors.Include("Books.Editions").AsEnumerable())
.ToTraceString()
是
SELECT
`Project1`.`Id`,
`Project1`.`Name`,
`Project1`.`C2` AS `C1`,
`Project1`.`id1`,
`Project1`.`AuthorId`,
`Project1`.`C1` AS `C2`,
`Project1`.`id2`,
`Project1`.`Title`
FROM (SELECT
`Extent1`.`Id`,
`Extent1`.`Name`,
`Join2`.`Id` AS `id1`,
`Join2`.`AuthorId`,
`Join2`.`Id` AS `id2`,
`Join2`.`Title`,
CASE WHEN (`Join2`.`Id` IS NULL) THEN (NULL)
WHEN (`Join2`.`BookId` IS NULL) THEN (NULL)
ELSE (1) END AS `C1`,
CASE WHEN (`Join2`.`Id` IS NULL) THEN (NULL)
ELSE (1) END AS `C2`
FROM `authors` AS `Extent1`
LEFT OUTER JOIN (SELECT
`Extent2`.`Id`,
`Extent2`.`AuthorId`,
`Join1`.`BookId`,
`Join1`.`EditionId`,
`Join1`.`Id` AS `Id1`,
`Join1`.`Title`
FROM `books` AS `Extent2`
LEFT OUTER JOIN (SELECT
`Extent3`.`BookId`,
`Extent3`.`EditionId`,
`Extent4`.`Id`,
`Extent4`.`Title`
FROM `editionsinbooks` AS `Extent3`
INNER JOIN `editions` AS `Extent4`
ON `Extent4`.`Id` = `Extent3`.`EditionId`) AS `Join1`
ON `Extent2`.`Id` = `Join1`.`BookId`) AS `Join2`
ON `Extent1`.`Id` = `Join2`.`AuthorId`) AS `Project1`
ORDER BY
`Project1`.`Id` ASC,
`Project1`.`C2` ASC,
`Project1`.`id1` ASC,
`Project1`.`C1` ASC
的CASE
語句是有趣的,因爲沒有我的MySQL字段是空。
您能否顯示作者,書籍和版本表的全部內容?我猜你在那裏有更多的數據而不是滿足眼睛,甚至可能有重複的信息,並且include語句重新排序,使First()返回一個不同的作者。 – doctorless
我必須在這裏同意@d_r_w。你可以嘗試輸出作者以及書籍嗎? –
@d_r_w @John查看我的編輯。另外,如果我輸出「edition.Id +」 - 「+ book.Id +」 - 「+ author.Id」,它會得到正確的書籍ID和作者ID,但是版本ID與書籍ID相同。 – James